示例#1
0
class CelticKnotwork(App):
    '''Main tabbed interface, each tab contains its own instance of CelticKnotwork2'''
    def build(self):
        ##Instance Variables
        self.showDots = True
        self.showGrid = True
        self.showBreaklines = True
        self.showSkeleton = True
        self.showKnot = True
        self.knotX = 4
        self.knotY = 4
        self.knotWidth = 8
        self.knotWidthView = 8
        self.gridUnits = 50
        self.gridUnitsView = 50
        self.offsetX = 150
        self.offsetY = 50
        self.totTabs = 1
        self.tabNo = 1
        
        
        ##Main Layout
        self.layout_main = AnchorLayout(anchor_x = "left", anchor_y="top")
        self.layout_tabs= FloatLayout(size=(Window.width, Window.height), size_hint=(0.1, 0.08))

        
        ##Top Tab Bar - allowing multiple knots
        self.tp = TabbedPanel()
        self.tp.default_tab_text = "Knot 1"
        self.layout_main.add_widget(self.tp)
        self.addTab = TabbedPanelHeader(text='+')
        self.addTab.bind(on_release = self.onPressAddTab)
        self.addTab = Button(text='+', pos =(Window.width*.9,Window.height*.92))
        self.addTab.bind(on_press = self.onPressAddTab)
        self.tp.default_tab_content = CelticKnotwork2().build() #get tab content from CelticKnotwork2
        self.layout_tabs.add_widget(self.addTab)
        self.layout_main.add_widget(self.layout_tabs)

        Window.bind(on_resize=self.on_resize)

        
        
        return self.layout_main
    def onPressAddTab(self, instance):
        '''Add a tab when "+" button pressed'''
        self.totTabs += 1
        self.tabNo = self.totTabs
        self.th = TabbedPanelHeader(text='Knot '+str(self.totTabs))
        self.th.content = CelticKnotwork2().build()
        self.tp.add_widget(self.th)
        
        self.tp.switch_to(self.th)
    def on_resize(self, window, height, somethingesle):
        '''Handles window resize'''
        self.layout_main.remove_widget(self.layout_tabs)
        self.layout_tabs= FloatLayout(size=(Window.width, Window.height), size_hint=(0.1, 0.05))
        self.addTab = Button(text='+', pos =(Window.width*.9,Window.height*.95))
        self.addTab.bind(on_press = self.onPressAddTab)
        self.layout_tabs.add_widget(self.addTab)
        self.layout_main.add_widget(self.layout_tabs)
示例#2
0
class MainGrid(GridLayout):
    def __init__(self, queue, runs_len, **kwargs):
        super(MainGrid, self).__init__(**kwargs)

        self.queue = queue
        self.runs_len = runs_len
        self.cores = []
        self.tabs = []

        self.cols = 1

        self.tabbedPanel = TabbedPanel()
        self.tabbedPanel.do_default_tab = False
        self.add_widget(self.tabbedPanel)

        Clock.schedule_interval(self.update_info, 0.1)

    def update_info(self, dt):

        if not self.queue.empty():
            cores = [tab.process for tab in self.tabs]
            element = self.queue.get()
            process, model = element["model"]

            if process not in cores:
                new_tab = TabWithInfo(process, self.runs_len)
                new_tab.text = f"Process {len(cores) + 1}"

                self.tabs.append(new_tab)
                self.tabbedPanel.add_widget(new_tab)
                self.tabbedPanel.switch_to(new_tab)

            current_tab = list(
                filter(lambda x: x.process == process, self.tabs))[0]

            current_tab.updateTab(element)
示例#3
0
class GameScreen(Screen):
    # on_enter is used instead of __init__ as we require SelectableGrid.chosen to be not empty and contain the names of the three Pokemon selected by the player.
    def on_enter(self):
        # Start by bringing in the global dictionary pokemon_info
        global pokemon_info
        # Initiate variables for the Pokemon chosen by the player, number of Pokemon beaten, number of trainers beaten, and possible Pokemon that can be generated.
        player_pokemon = SelectableGrid.chosen
        self.btn = SoundLoader.load('assets/button.wav')
        self.pkm_beaten = 0
        self.yours_beaten = 0
        self.trainers_beaten = 0
        self.pbl_images = [
            'assets/threeballs.png', 'assets/twoballs.png',
            'assets/oneball.png'
        ]
        self.possible_pokemon = list(pokemon_info.keys())
        # Create three variables, each one an instance of the Pokemon class, as well as randomize an opposing Pokemon from the pool of Pokemon as an instance of the Pokemon class.
        self.pkm1, self.pkm2, self.pkm3 = Pokemon(player_pokemon[0]), Pokemon(
            player_pokemon[1]), Pokemon(player_pokemon[2])
        self.opkm = Pokemon(random.choice(self.possible_pokemon))
        # Simulating a DS, our layout will start with the BoxLayout in vertical form.
        self.layout = BoxLayout(orientation='vertical')
        # self.top_screen displays the information for the player, including the current and max HP of both Pokemon, their levels, names, sprites.
        self.top_screen = GridLayout(cols=2, rows=2, size_hint=(1, 0.7))
        # Sets up and displays the opposing Pokemon's name, health, and level.
        self.opponent_info = GridLayout(cols=1, rows=3, size_hint=(1, 0.5))
        self.opponent_name_level = Label(text=self.opkm.name + '   Lv50',
                                         font_size=18,
                                         valign='middle',
                                         halign='left')
        self.opponent_info.add_widget(self.opponent_name_level)
        self.opponent_hp = Label(text=str(self.opkm.chp) + '/' +
                                 str(self.opkm.maxhp),
                                 font_size=16,
                                 valign='top')
        self.opponent_info.add_widget(self.opponent_hp)
        self.opponent_pkm_left = Image(source=self.pbl_images[self.pkm_beaten])
        self.opponent_info.add_widget(self.opponent_pkm_left)
        self.top_screen.add_widget(self.opponent_info)
        # Displays the image for both Pokemon.
        self.oimg = Image(source=self.opkm.imgf)
        self.top_screen.add_widget(self.oimg)
        self.mimg = Image(source=self.pkm1.imgb)
        self.top_screen.add_widget(self.mimg)
        # Sets up and displays my Pokemon's name, health, and level.
        self.my_info = GridLayout(cols=1, rows=3, size_hint=(1, 0.5))
        self.my_name_level = Label(text=self.pkm1.name + '   Lv50',
                                   font_size=18,
                                   valign='middle',
                                   halign='left')
        self.my_info.add_widget(self.my_name_level)
        self.my_hp = Label(text=str(self.pkm1.chp) + '/' +
                           str(self.pkm1.maxhp),
                           font_size=16,
                           valign='top')
        self.my_info.add_widget(self.my_hp)
        self.my_pkm_left = Image(source=self.pbl_images[self.yours_beaten])
        self.my_info.add_widget(self.my_pkm_left)
        # Add the whole of the top screen into the main layout.
        self.top_screen.add_widget(self.my_info)
        self.layout.add_widget(self.top_screen)
        # Create and add a label that shows the progress of the battle, which will be constantly updated as the user takes action.
        self.textbox = Label(text='Battle progress shows up here!',
                             font_size=14,
                             valign='top',
                             halign='center',
                             size_hint=(1, 0.3))
        self.layout.add_widget(self.textbox)
        # The bottom screen will allow the user to put in their actions. In our case, we do not need the 'Bag' and 'Run' tab from the original Pokemon game, so a TabbedPanel spanning two tab items would suffice.
        self.btm_screen = TabbedPanel(do_default_tab=False, tab_width=250)
        # Add in our tabs, either to fight or to switch out.
        self.fight_tab = TabbedPanelItem(text='Fight')
        self.switch_tab = TabbedPanelItem(text='Pokemon')
        # Creating the page for using a move, which is selected initially
        self.fight_page = GridLayout(cols=2,
                                     col_default_width=250,
                                     col_force_default=True,
                                     row_default_height=150,
                                     row_force_default=True)
        # Initializing the moves for all three Pokemon.
        self.pkm1_moves = pokemon_info[self.pkm1.name]['moves']
        self.pkm2_moves = pokemon_info[self.pkm2.name]['moves']
        self.pkm3_moves = pokemon_info[self.pkm3.name]['moves']
        # Adding buttons for each move the Pokemon has.
        self.move1_btn = Button(
            text=self.pkm1_moves[0] + '\n' + 'PP: ' +
            str(self.pkm1.this_moveset[self.pkm1_moves[0]]['cPP']) + '/' +
            str(self.pkm1.this_moveset[self.pkm1_moves[0]]['PP']) + '\n' +
            'Type: ' + str(self.pkm1.this_moveset[self.pkm1_moves[0]]['Type']),
            font_size=16,
            halign='center',
            on_press=self.use_attack)
        self.move2_btn = Button(
            text=self.pkm1_moves[1] + '\n' + 'PP: ' +
            str(self.pkm1.this_moveset[self.pkm1_moves[1]]['cPP']) + '/' +
            str(self.pkm1.this_moveset[self.pkm1_moves[1]]['PP']) + '\n' +
            'Type: ' + str(self.pkm1.this_moveset[self.pkm1_moves[1]]['Type']),
            font_size=16,
            halign='center',
            on_press=self.use_attack)
        self.move3_btn = Button(
            text=self.pkm1_moves[2] + '\n' + 'PP: ' +
            str(self.pkm1.this_moveset[self.pkm1_moves[2]]['cPP']) + '/' +
            str(self.pkm1.this_moveset[self.pkm1_moves[2]]['PP']) + '\n' +
            'Type: ' + str(self.pkm1.this_moveset[self.pkm1_moves[2]]['Type']),
            font_size=16,
            halign='center',
            on_press=self.use_attack)
        self.move4_btn = Button(
            text=self.pkm1_moves[3] + '\n' + 'PP: ' +
            str(self.pkm1.this_moveset[self.pkm1_moves[3]]['cPP']) + '/' +
            str(self.pkm1.this_moveset[self.pkm1_moves[3]]['PP']) + '\n' +
            'Type: ' + str(self.pkm1.this_moveset[self.pkm1_moves[3]]['Type']),
            font_size=16,
            halign='center',
            on_press=self.use_attack)
        self.fight_page.add_widget(self.move1_btn)
        self.fight_page.add_widget(self.move2_btn)
        self.fight_page.add_widget(self.move3_btn)
        self.fight_page.add_widget(self.move4_btn)
        self.fight_tab.add_widget(self.fight_page)
        # Creating the page to switch out.
        self.switch_page = BoxLayout(orientation='horizontal')
        # Display the names of the other two Pokemon as well as their HP.
        self.pkm1_btn = Button(text=self.pkm2.name + '\n' +
                               str(self.pkm2.chp) + '/' + str(self.pkm2.maxhp),
                               font_size=16,
                               halign='center',
                               on_press=self.switch1)
        self.pkm2_btn = Button(text=self.pkm3.name + '\n' +
                               str(self.pkm3.chp) + '/' + str(self.pkm3.maxhp),
                               font_size=16,
                               halign='center',
                               on_press=self.switch2)
        self.switch_page.add_widget(self.pkm1_btn)
        self.switch_page.add_widget(self.pkm2_btn)
        self.switch_tab.add_widget(self.switch_page)
        self.btm_screen.add_widget(self.fight_tab)
        self.btm_screen.add_widget(self.switch_tab)
        # Add the bottom screen into the layout, and add the layout into the screen.
        self.layout.add_widget(self.btm_screen)
        self.add_widget(self.layout)

    # When a transition happens from this screen to the selection screen, remove all widgets so that on_enter does not create a second layer of widgets.
    def on_leave(self):
        self.clear_widgets()

    # The switch function for both Pokemon slots. Checks if the current HP of Pokemon to switch to is 0, if so, do not allow the switch.
    def switch1(self, instance):
        self.btn.play()
        if self.pkm2.chp == 0:
            SimplePopup.open(self, 'This Pokemon has fainted!')
        else:
            self.pkm1, self.pkm2 = self.pkm2, self.pkm1
            self.update()
            self.btm_screen.switch_to(self.fight_tab)

    def switch2(self, instance):
        self.btn.play()
        if self.pkm3.chp == 0:
            SimplePopup.open(self, 'This Pokemon has fainted!')
        else:
            self.pkm1, self.pkm3 = self.pkm3, self.pkm1
            self.update()
            self.btm_screen.switch_to(self.fight_tab)

    # Binded to each button with a move, this function is called whenever an attack is used.
    def use_attack(self, instance):
        # Check if the using Pokemon is fainted first, and prompt the user to switch out of it is.
        self.btn.play()
        if self.pkm1.chp == 0:
            SimplePopup.open(
                self, 'Your current Pokemon has fainted, please switch out!')
        else:
            # Take the text in the button and split it so we can take the first word, the name of the move.
            move = instance.text.split('\n')[0]
            # Call use_move from the Pokemon class to execute the move.
            self.pkm1.use_move(self.opkm, move, self)
            # If the opposing Pokemon faints, increase pkm_beaten by 1.
            if self.opkm.chp == 0:
                self.pkm_beaten += 1
                # If three consecutive defeats have happened, change pkm_beaten to 0, and add 1 to trainer beaten. Restore health and PP to all the player's Pokemon, and display a prompt that tells the player that their Pokemon are restored, as well as the number of trainers beaten.
                if self.pkm_beaten == 3:
                    self.yours_beaten = 0
                    self.pkm_beaten = 0
                    self.trainers_beaten += 1
                    self.pkm1.chp = self.pkm1.maxhp
                    self.pkm2.chp = self.pkm2.maxhp
                    self.pkm3.chp = self.pkm3.maxhp
                    for i in range(4):
                        self.pkm1.this_moveset[self.pkm1_moves[i]][
                            'cPP'] = self.pkm1.this_moveset[
                                self.pkm1_moves[i]]['PP']
                        self.pkm2.this_moveset[self.pkm2_moves[i]][
                            'cPP'] = self.pkm2.this_moveset[
                                self.pkm2_moves[i]]['PP']
                        self.pkm3.this_moveset[self.pkm3_moves[i]][
                            'cPP'] = self.pkm3.this_moveset[
                                self.pkm3_moves[i]]['PP']
                    SimplePopup.open(
                        self,
                        'You\'ve beaten a trainer!\nYour Pokemon will now be fully healed.\n'
                        + 'Trainers Beaten: ' + str(self.trainers_beaten))
                # Randomize a new Pokemon for the opponent, and also preventing it from being the last Pokemon to prevent duplicates.
                self.opkm = Pokemon(
                    random.choice([
                        x for x in self.possible_pokemon if x != self.opkm.name
                    ]))
            # Call the update function.
            self.update()

    # The update function updates the game state. After each move or switchout, it will change everything as necessary, be it the health of both Pokemon, the sprites displayed, the moves available for your Pokemon, and PP of the moves, etc.
    def update(self):
        # If all the player's Pokemon are fainted, that means the player loses, sadly. Allow the player to restart their run with new Pokemon by bringing them back to the selection screen. Note that the on_leave function is also called to clear all the widgets.
        if self.yours_beaten == 3:
            self.yours_beaten = 0
            SimplePopup.open(
                self,
                'All your Pokemon have fainted!\nYou will be brought to the selection screen to restart your run.'
            )
            self.manager.transition = NoTransition()
            self.manager.current = 'selection'
        self.opponent_name_level.text = self.opkm.name + '   Lv50'
        self.opponent_hp.text = str(self.opkm.chp) + '/' + str(self.opkm.maxhp)
        self.oimg.source = self.opkm.imgf
        self.mimg.source = self.pkm1.imgb
        self.my_name_level.text = self.pkm1.name + '   Lv50'
        self.my_hp.text = str(self.pkm1.chp) + '/' + str(self.pkm1.maxhp)
        self.pkm1_moves = pokemon_info[self.pkm1.name]['moves']
        self.move1_btn.text = self.pkm1_moves[0] + '\n' + 'PP: ' + str(
            self.pkm1.this_moveset[self.pkm1_moves[0]]['cPP']) + '/' + str(
                self.pkm1.this_moveset[
                    self.pkm1_moves[0]]['PP']) + '\n' + 'Type: ' + str(
                        self.pkm1.this_moveset[self.pkm1_moves[0]]['Type'])
        self.move2_btn.text = self.pkm1_moves[1] + '\n' + 'PP: ' + str(
            self.pkm1.this_moveset[self.pkm1_moves[1]]['cPP']) + '/' + str(
                self.pkm1.this_moveset[
                    self.pkm1_moves[1]]['PP']) + '\n' + 'Type: ' + str(
                        self.pkm1.this_moveset[self.pkm1_moves[1]]['Type'])
        self.move3_btn.text = self.pkm1_moves[2] + '\n' + 'PP: ' + str(
            self.pkm1.this_moveset[self.pkm1_moves[2]]['cPP']) + '/' + str(
                self.pkm1.this_moveset[
                    self.pkm1_moves[2]]['PP']) + '\n' + 'Type: ' + str(
                        self.pkm1.this_moveset[self.pkm1_moves[2]]['Type'])
        self.move4_btn.text = self.pkm1_moves[3] + '\n' + 'PP: ' + str(
            self.pkm1.this_moveset[self.pkm1_moves[3]]['cPP']) + '/' + str(
                self.pkm1.this_moveset[
                    self.pkm1_moves[3]]['PP']) + '\n' + 'Type: ' + str(
                        self.pkm1.this_moveset[self.pkm1_moves[3]]['Type'])
        self.pkm1_btn.text = self.pkm2.name + '\n' + str(
            self.pkm2.chp) + '/' + str(self.pkm2.maxhp)
        self.pkm2_btn.text = self.pkm3.name + '\n' + str(
            self.pkm3.chp) + '/' + str(self.pkm3.maxhp)
        self.pkm1_moves = pokemon_info[self.pkm1.name]['moves']
        self.pkm2_moves = pokemon_info[self.pkm2.name]['moves']
        self.pkm3_moves = pokemon_info[self.pkm3.name]['moves']
        self.opponent_pkm_left.source = self.pbl_images[self.pkm_beaten]
        self.my_pkm_left.source = self.pbl_images[self.yours_beaten]
        if self.pkm1.chp == 0:
            self.btm_screen.switch_to(self.switch_tab)
示例#4
0
class TabbedPanelApp(App):
    def __init__(self) -> None:
        App.__init__(self)

        #Allows access to controller class to send signals
        self.Controller = Controller()

        #For GPS/Mapping
        self.TargetInfo = TargetInfo()

        self.tp = None
        self.th_drone_control = None
        self.th_drone_adv_control = None
        self.th_doc = None

        Cache.remove('kv.image')
        Cache.remove('kv.texture')

        image = Image.open("Gmap/default.png")
        temp = image.copy()
        temp.save("Gmap/drone_path.png")

        image = Image.open("images/default_score.png")
        temp = image.copy()
        temp.save("images/scored.png")
        temp.save("images/prescored.png")
    
    def build(self) -> 'kivy.uix.tabbedpanel.TabbedPanel':
        self.tp = TabbedPanel()
        self.tp.tab_width = 500
        

        #Default tab: Main Controller
        self.tp.default_tab_text = "Main Controller Page"
        self.tp.default_tab_content = ControllerView()
        self.tp.default_tab.background_normal = 'images/strong_blue.png'
        self.tp.default_tab.background_down = 'images/lime_green.png'

        #Drone Control
        self.th_drone_adv_control = TabbedPanelHeader(text='Drone Control')
        self.th_drone_adv_control.content= DroneView()
        self.th_drone_adv_control.background_normal = 'images/strong_blue.png'
        self.th_drone_adv_control.background_down = 'images/lime_green.png'

        #Drone Control
        self.th_drone_control = TabbedPanelHeader(text='DIPS and Mapping')
        self.th_drone_control.content= DroneAdvView()
        self.th_drone_control.background_normal = 'images/strong_blue.png'
        self.th_drone_control.background_down = 'images/lime_green.png'

        #Documentation
        self.th_doc = TabbedPanelHeader(text='Documentation')
        self.th_doc.content= DocView()
        self.th_doc.background_normal = 'images/strong_blue.png'
        self.th_doc.background_down = 'images/lime_green.png'        

        self.tp.add_widget(self.tp.default_tab)
        self.tp.add_widget(self.th_drone_adv_control)
        self.tp.add_widget(self.th_drone_control)
        self.tp.add_widget(self.th_doc)

        return self.tp

    def do_directcheck(self, throttle_text, yaw_text, pitch_text, roll_text, aux1_text, aux2_text, *args) -> bool:
        if throttle_text == '' or yaw_text == '' or \
           pitch_text == '' or roll_text == '':
            return False
        else:
            try:
                throttle_text = int(throttle_text)
                yaw_text = int(yaw_text)
                pitch_text = int(pitch_text)
                roll_text = int(roll_text)
                aux1_text = int(aux1_text)
                aux2_text = int(aux2_text)
            except ValueError:
                return False
            else:
                self.Controller.Throttle = throttle_text
                self.Controller.Yaw = yaw_text
                self.Controller.Pitch = pitch_text
                self.Controller.Roll = roll_text
                self.Controller.AUX1 = aux1_text
                self.Controller.AUX2 = aux2_text

                return self.Controller.DirectValueCheck()

    def do_rampcheck(self, *args) -> None:
        return self.Controller.RampValueCheck()

    def set_s1(self, value) -> None:
        self.Controller.Throttle_Ramp = value

    def set_s2(self, value) -> None:
        self.Controller.Yaw_Ramp = value

    def set_s3(self, value) -> None:
        self.Controller.Pitch_Ramp = value

    def set_s4(self, value) -> None:
        self.Controller.Roll_Ramp = value

    def available_ports(self) -> list:
        ports = self.Controller.PortCheck()

        if ports:
            return ports
        return ['None']

    def check_connect(self) -> bool:
        return self.Controller.CheckConnect()

    def do_setup(self, port, bauds) -> bool:
        if port == 'None' or bauds == 'None':
            return False

        Connection = self.Controller.Connect(port, int(bauds))
        self.TargetInfo.ParsingSetup(self.Controller.ReturnSerial())

        return Connection

    def startup(self) -> None:
        self.Controller.Startup()

    def up(self) -> bool:
        self.Controller.Prev_Val = self.Controller.Ramping.PreviousValues()
        if len(self.Controller.Prev_Val) != 0:
            return self.Controller.Up()
        return False

    def down(self) -> bool:
        self.Controller.Prev_Val = self.Controller.Ramping.PreviousValues()
        if len(self.Controller.Prev_Val) != 0:
            return self.Controller.Down()
        return False

    def forward(self) -> bool:
        self.Controller.Prev_Val = self.Controller.Ramping.PreviousValues()
        if len(self.Controller.Prev_Val) != 0:
            return self.Controller.Forward()
        return False

    def backward(self) -> bool:
        self.Controller.Prev_Val = self.Controller.Ramping.PreviousValues()
        if len(self.Controller.Prev_Val) != 0:
            return self.Controller.Backward()
        return False

    def right(self) -> bool:
        self.Controller.Prev_Val = self.Controller.Ramping.PreviousValues()
        if len(self.Controller.Prev_Val) != 0:
            return self.Controller.Right()
        return False

    def left(self) -> bool:
        self.Controller.Prev_Val = self.Controller.Ramping.PreviousValues()
        if len(self.Controller.Prev_Val) != 0:
            return self.Controller.Left()
        return Falses

    def hover(self) -> bool:
        self.Controller.Prev_Val = self.Controller.Ramping.PreviousValues()
        if len(self.Controller.Prev_Val) != 0:
            return self.Controller.Hover()
        return False

    def abort(self) -> None:
        self.Controller.Abort()

    def disconnect(self) -> None:
        self.Controller.Disconnect()
        
    def do_check_latlong(self, *args) -> bool:
        return self.TargetInfo.LatLongCheck(*args)

    def test_path(self, *args) -> None:
        self.TargetInfo.TestPath()        

    def threading_read(self, *args) -> None:
        t = threading.Thread(target = self.read_gps, args = ())
        t.start()

    def read_gps(self) -> bool:
        time.sleep(2)
        return self.TargetInfo.ReadGPS()

    def find_start(self) -> None:
        self.TargetInfo.SetStart()

    def load_gif(self, *args) -> None:
        image = Image.open("images/loading.png")
        temp = image.copy()
        temp.save("Gmap/drone_path.png")

    def retrieveNumTargets(self, *args) -> int:
        try:
            nt = int(args[0])
            if nt > 0 and nt <= 10:
                return nt
            else:
                return -1
        except:
            return -1

    def setnumtargets(self, *args) -> None:
        self.TargetInfo.Setup(args[0])

    def shownumtargets(self, *args) -> None:
        return self.TargetInfo.NumTargets()

    def targets_sent(self, *args) -> None:
        self.TargetInfo.TargetsSet()

    def targets_sent_check(self, *args) -> None:
        return self.TargetInfo.targets_sent

    def switch_tab(self, *args) -> None:
        self.tp.switch_to(self.tp.default_tab)
        '''
    def drawInformationContainer(self):
        information_layout = BoxLayout(orientation='vertical',
                                       size_hint=(1 - skinContainerSize, 1))
        championNameLayout = RelativeLayout(size_hint=(1, 0.15))

        infoSize = (Window.width) * (1 - skinContainerSize)
        infoSize = math.floor(infoSize / 5)

        championName = Label(text=self.championName,
                             font_size='32sp',
                             pos_hint={
                                 'middle': 1,
                                 'top': 1
                             })
        back_button = Button(
            on_press=lambda back: self.returnToSearch(),
            background_normal='images\\icons\\back-arrow-white.png',
            background_down='images\\icons\\back-arrow-white_pressed.png',
            size_hint=(0.03, 0.2),
            pos_hint={
                'right': 0.98,
                'y': 0.75
            },
            border=(0, 0, 0, 0))
        tp = TabbedPanel(tab_pos='top_mid',
                         padding=(dp(20), dp(2), dp(2), dp(2)),
                         tab_width=infoSize,
                         do_default_tab=False,
                         size_hint=(1, 0.85))

        labelText = TabbedPanelItem(text="Statistics",
                                    background_color=(0, 0, 0, 0),
                                    halign="left",
                                    disabled_color=hex('#ffffff'),
                                    font_size=20)
        labelText.disabled = True
        defenseTab = TabbedPanelItem(id='defenseTab',
                                     background_color=hex('#5BBD80'),
                                     text='Defense',
                                     content=self.drawDefenseLayoutContent())
        offenseTab = TabbedPanelItem(background_color=hex('#C3403C'),
                                     text='Offensive',
                                     content=self.drawOffensiveLayoutContent())
        rangesTab = TabbedPanelItem(background_color=hex('#0988DB'),
                                    text='Ranges',
                                    content=self.drawRangesLayoutContent())
        abilitiesTab = TabbedPanelItem(
            background_color=hex('#E1E135'),
            text='Abilities',
            content=self.drawAbilitiesLayoutContent())

        tp.add_widget(labelText)
        tp.add_widget(defenseTab)
        tp.add_widget(offenseTab)
        tp.add_widget(rangesTab)
        tp.add_widget(abilitiesTab)

        #switches the tabbed panel to whatever we want to set as our default
        Clock.schedule_once(lambda dt: tp.switch_to(defenseTab), 0.1)
        championNameLayout.add_widget(championName)
        championNameLayout.add_widget(back_button)
        information_layout.add_widget(championNameLayout)
        information_layout.add_widget(tp)
        return information_layout
示例#6
0
    def __init__(self, df, security_name, **kwargs):
        super(Application, self).__init__(**kwargs)
        self.orientation = 'vertical'
        tab_panel = TabbedPanel()
        tab_panel.do_default_tab = False
        tab_panel.background_color = (7 / 255, 0, 13 / 255, 1)
        tab_menu = TabbedPanelItem(text="Menu")
        tab_menu.background_color = (62 / 255, 142 / 255, 222 / 255, 1)
        tab_chart = TabbedPanelItem(text='Chart')
        tab_chart.background_color = (62 / 255, 142 / 255, 222 / 255, 1)
        tab_training = TabbedPanelItem(text='Training')
        tab_training.background_color = (62 / 255, 142 / 255, 222 / 255, 1)
        tab_validate = TabbedPanelItem(text='Validate')
        tab_validate.background_color = (62 / 255, 142 / 255, 222 / 255, 1)
        tab_future = TabbedPanelItem(text='Prediction')
        tab_future.background_color = (62 / 255, 142 / 255, 222 / 255, 1)

        tab_panel.add_widget(tab_menu)
        tab_panel.add_widget(tab_chart)
        tab_panel.add_widget(tab_training)
        tab_panel.add_widget(tab_validate)
        tab_panel.add_widget(tab_future)

        tab_menu.bind(on_press=lambda x: change_screen('menu'))

        chart_layout = FloatLayout()
        fig = plot_data(df, security_name.upper(), 30, 200)
        canvas = fig.canvas
        chart_layout.add_widget(canvas)
        tab_chart.add_widget(chart_layout)

        predict_frame = FloatLayout(opacity=1)
        predict_btn = Button(text='Run Prediction',
                             background_color=(62 / 255, 142 / 255, 222 / 255,
                                               1),
                             font_size=20,
                             pos_hint={
                                 "center_x": 0.5,
                                 "bottom": 0
                             },
                             size_hint=(0.3, 0.075))

        predict_btn.bind(on_press=lambda x: start_predict(df, security_name))
        predict_frame.add_widget(predict_btn)
        chart_layout.add_widget(predict_frame)

        def start_predict(df, security_name):
            que = queue.Queue()
            par_modeling = partial(modeling, security_name=security_name)
            process = threading.Thread(
                target=lambda q, arg1: q.put(par_modeling(arg1)),
                args=(que, df),
                daemon=True)
            process.start()

            Clock.schedule_once(
                lambda *args: tab_panel.switch_to(tab_training))

            train_fig = plt.figure(facecolor='#07000d')
            train_canvas = train_fig.canvas
            train_layout = FloatLayout()
            train_layout.add_widget(train_canvas)
            tab_training.add_widget(train_layout)

            if os.path.exists('training.csv'):
                os.remove('training.csv')

            def update_plot(fig):
                train_canvas = fig.canvas
                train_layout.clear_widgets()
                train_layout.add_widget(train_canvas)
                plt.close(fig)
                # for child in train_layout.children[:1]:
                #     train_layout.remove_widget(child)
                # Clock.schedule_once(lambda *args: tab_panel.switch_to(tab_training))

            def read_training(self):
                if os.path.exists('training.csv'):
                    loss_df = None
                    try:
                        loss_df = pd.read_csv('training.csv')
                    except Exception as e:
                        print(e)
                        pass
                    if loss_df is not None:
                        train_fig = plot_loss(loss_df)
                        update_plot(train_fig)
                if not process.is_alive():
                    Clock.unschedule(read_training)
                    val_fig, future_fig = que.get()
                    val_canvas = val_fig.canvas
                    val_layout = FloatLayout()
                    val_layout.add_widget(val_canvas)
                    tab_validate.add_widget(val_layout)

                    future_canvas = future_fig.canvas
                    future_layout = FloatLayout()
                    future_layout.add_widget(future_canvas)
                    tab_future.add_widget(future_layout)

                    Clock.schedule_once(
                        lambda *args: tab_panel.switch_to(tab_validate))

            Clock.schedule_interval(read_training, 0.1)

        Clock.schedule_once(lambda *args: tab_panel.switch_to(tab_chart))

        self.add_widget(tab_panel)
示例#7
0
 def switch_to(self, header):
     TabbedPanel.switch_to(self, header)
     if self.on_tab_switch:
         self.on_tab_switch(header)
示例#8
0
class StockPage(GridLayout):



    def __init__(self, **kwargs):

        super(StockPage, self).__init__(**kwargs)
        # self.height = 500
        # self.size_hint_y = None
        # self.width  = 300
        self.rows = 2
        App.title = "StockQuick"

        #Top Bar

        #Heigth
        top_height = 30

        self.top_bar = BoxLayout(orientation='horizontal',spacing=10,height=top_height + 4,size_hint_y=(None))
        top_bar = self.top_bar

        top_bar.add_widget(Label(text='',size_hint_x=(.5),height=top_height,size_hint_y=(None)))

        top_bar.add_widget(Label(text='Enter Ticker(s):',size=(85,top_height),size_hint=(None,None)))
        self.ticker = TextInput(text='',multiline=False,size=(200,top_height),size_hint=(None,None))
        self.ticker.bind(on_text_validate=self.enter)
        top_bar.add_widget(self.ticker)
        self.submit = Button(text='Submit',size=(75,top_height),size_hint=(None,None))
        self.submit.bind(on_press=self.enter)
        top_bar.add_widget(self.submit)

        top_bar.add_widget(Label(text='',size_hint_x=(.5),height=top_height,size_hint_y=(None)))

        self.add_widget(top_bar)


        #Stock Section (Dot notation kept to show structure)

        self.tab_box = TabbedPanel()
        tab_box = self.tab_box
        tab_box.background_color = [1,1,1,1]
        tab_box.do_default_tab = False
        tab_box.tab_height = 30
        tab_box.tab_width = 60



        self.quotes_header = TabbedPanelHeader(text='Quotes')
        self.quotes_height = 30
        self.stock_list = []
        self.quotes_blank = Label(text='',size_hint_x=(0.5))

        self.quotes_grid = GridLayout(cols=7,row_default_height=self.quotes_height,row_force_default=True)
        self.live_button = ToggleButton(text='Live',state='normal',size_hint_x=(0.125))
        self.live_button.bind(on_press=self.update)
        self.quotes_grid.add_widget(self.live_button)
        # self.tab_box.quotes_th.quotes_grid.add_widget(self.quotes_blank)
        # self.tab_box.quotes_th.quotes_grid.add_widget(Label(text='Ticker',size_hint_x=(0.125)))
        self.quotes_grid.add_widget(Label(text='Current',size_hint_x=(0.125)))
        self.quotes_grid.add_widget(Label(text='Open',size_hint_x=(0.125)))
        self.quotes_grid.add_widget(Label(text='High',size_hint_x=(0.125)))
        self.quotes_grid.add_widget(Label(text='Low',size_hint_x=(0.125)))
        self.quotes_grid.add_widget(Label(text='Close',size_hint_x=(0.125)))

        self.remove_all = Button(text="Clear",size_hint_x=(0.125))
        self.remove_all.bind(on_press=self.clearStocks)
        self.quotes_grid.add_widget(self.remove_all)
        self.quotes_header.content = self.quotes_grid
        tab_box.add_widget(self.quotes_header)




        # self.options_header = TabbedPanelHeader(text='Options')
        # self.options_header.content = self.optionsTab()
        # tab_box.add_widget(self.options_header)



        self.add_widget(self.tab_box)

        # self.tab_box.switch_to(self.quotes_header)
        Clock.schedule_once(lambda *args: self.tab_box.switch_to(self.quotes_header))
        # Clock.schedule_once(partial(self.switch, tab1), 0)


    def update(self,event):
        if self.live_button.state == 'down':
            self.event = Clock.schedule_interval(self.live,0.5)




    def live(self,event):
        # for stock in self.stock_list:
        #     stock.updateLabel()
        symbols = '?symbols='
        i = 0
        for stock in self.stock_list:
            if i != 0:
                symbols += ',' + stock.getTick()
            else:
                symbols += stock.getTick()
                i += 1

        url = 'https://api.iextrading.com/1.0/stock/market/batch'
        url += symbols + "&types=price,ohlc"
        # url += symbols + "&filter=lastSalePrice"


        r = requests.get(url)
        output = r.json()
        print(output)
        for stock in self.stock_list:
            ticker = stock.getTick().upper()
            price = str(output.get(ticker).get('price'))
            open = str(output.get(ticker).get('ohlc').get('open').get('price'))
            close = str(output.get(ticker).get('ohlc').get('close').get('price'))
            high = str(output.get(ticker).get('ohlc').get('high'))
            low = str(output.get(ticker).get('ohlc').get('low'))
            stock.updateLabel(price)
            stock.open_label.text = open
            stock.high_label.text = high
            stock.low_label.text = low
            stock.close_label.text = close
        if self.live_button.state == 'normal':
            return False

    def findPrice(self,ticker):
        stock = Stock(ticker,source='yahoo')
        return(str(stock.price))

    def initStocks(self,event):
        self.clearStocks(event)

        tick_csv = self.ticker.text
        tick_list = tick_csv.split(",")
        for tick in tick_list:
            blank1 = Label(text='',size_hint_x=(0.125))
            tick_label = Label(text='',size_hint_x=(0.125))
            price_label = Label(text='',size_hint_x=(0.125))
            open_label = Label(text='',size_hint_x=(0.125))
            high_label = Label(text='',size_hint_x=(0.125))
            low_label = Label(text='',size_hint_x=(0.125))
            close_label = Label(text='',size_hint_x=(0.125))
            blank2 = Label(text='',size_hint_x=(0.125))
            type_label = Label(text='',size_hint_y=None)
            strike_label = Label(text='',size_hint_y=None)
            bid_label = Label(text='',size_hint_y=None)
            ask_label = Label(text='',size_hint_y=None)
            option_block = GridLayout(rows=2)
            new_Stock = MyStock(tick,blank1,tick_label,price_label,open_label,high_label,low_label,close_label,blank2,type_label,strike_label,bid_label,ask_label,option_block)

            self.stock_list.append(new_Stock)

            # self.tab_box.quotes_th.content.add_widget(new_Stock.getBlank1())
            self.quotes_grid.add_widget(new_Stock.getTickLabel())
            self.quotes_grid.add_widget(new_Stock.getPriceLabel())
            self.quotes_grid.add_widget(new_Stock.open_label)
            self.quotes_grid.add_widget(new_Stock.high_label)
            self.quotes_grid.add_widget(new_Stock.low_label)
            self.quotes_grid.add_widget(new_Stock.close_label)
            self.quotes_grid.add_widget(new_Stock.getBlank2())

            self.live(event)

    def enter(self,event):
        self.initStocks(event)


        # self.initOptions(event)

        # popup = Popup(title='Test popup',
        # content=Label(text='Hello world'),
        # size_hint=(None, None), size=(400, 400))
        #
        # popup.open()





    def clearStocks(self,event):
        trim = []
        for stock in self.stock_list:
            self.quotes_grid.clear_widgets(children=stock.getWidgets())
示例#9
0
class Demoer(FloatLayout):
    def __init__(self, *args, **kwargs):
        self.state = ToolState.EMPTY

        # dimensions of the area where nodes can be placed
        self.workAreaXDim = 720
        self.workAreaYDim = 520
        self.workAreaXPos = 40
        self.workAreaYPos = 40

        # multiple choice bubble menu for node addition
        self.defaultBubble = Bubble(size_hint=(None, None), size=(250, 40))
        self.newComputerButton = Button(text="Nowy komputer")
        self.newRouterButton = Button(text="Nowy router")
        self.defaultBubble.add_widget(self.newComputerButton)
        self.defaultBubble.add_widget(self.newRouterButton)

        # coordinates of node-button to be placed
        self.pendingNodePosX = 0
        self.pendingNodePosY = 0

        # multiple choice bubble menu for node editing/removal
        self.nodeBubble = Bubble(size_hint=(None, None), size=(250, 40))
        self.newConnButton = Button(text="Dodaj połączenie")
        self.deleteNodeButton = Button(text="Usuń węzeł")
        self.nodeBubble.add_widget(self.newConnButton)
        self.nodeBubble.add_widget(self.deleteNodeButton)

        # reference to button being edited/removed
        self.pendingNodeRef = Button()

        # global state - adding connection or not
        self.isInConnectionMode = False
        self.netManager = NetworkManager(self.__deleteLine, self.appendLog,
                                         self.animatePacket)

        # define widgets of side panel and add them to window
        self.sidePanelTabbedPanel = TabbedPanel(do_default_tab=False,
                                                size=(200, 600),
                                                pos=(800, 0),
                                                background_color=(0, 0, 0, 0),
                                                tab_width=100)

        # define widgets of log display and add them to window
        self.sidePanelLogTab = TabbedPanelItem(text="Symulacja")
        self.sidePanelLogLayout = GridLayout(cols=1,
                                             spacing=10,
                                             size_hint=(None, None),
                                             size=(200, 550))
        self.logField = TextInput(padding=10,
                                  readonly=True,
                                  size_hint_max_y=None,
                                  size_hint=(None, None),
                                  size=(190, 550))
        self.logField.bind(minimum_height=self.logField.setter('height'))
        self.sidePanelLogScrollView = ScrollView(
            size_hint=(None, None),
            size=(200, 450),
            scroll_type=['bars'],
            bar_width=10,
            bar_inactive_color=[1, 1, 1, .8],
            bar_color=[0.3, 1, 1, 1])
        self.sidePanelLogScrollView.add_widget(self.logField)
        self.sidePanelLogLayout.add_widget(self.sidePanelLogScrollView)
        self.sidePanelLogTab.add_widget(self.sidePanelLogLayout)
        self.sidePanelTabbedPanel.add_widget(self.sidePanelLogTab)

        # A welcome log
        self.appendLog('A new workspace has been created.')

        # define widgets of node edit panel to be added to window later
        # when a node is selected, add sidePanelNodeTab with the proper tab name to sidePanelTabbedPanel
        # and fill sidePanelNodeTab with content - interface configuration form
        self.sidePanelNodeTab = TabbedPanelItem()
        self.sidePanelNodeLayout = GridLayout(cols=1,
                                              spacing=5,
                                              size_hint=(None, None),
                                              size=(200, 550))
        self.sidePanelNodeLayout.bind(
            minimum_height=self.sidePanelNodeLayout.setter('height'))
        self.sidePanelNodeScrollView = ScrollView(
            size_hint=(None, None),
            size=(200, 550),
            pos=(800, 0),
            scroll_type=['bars'],
            bar_width=10,
            bar_inactive_color=[1, 1, 1, .8],
            bar_color=[1, 1, 1, 1])
        self.sidePanelNodeTab.add_widget(self.sidePanelNodeScrollView)
        self.sidePanelNodeScrollView.add_widget(self.sidePanelNodeLayout)

        # define simulation-related buttons and add them to the window
        self.toggleSimButton = Button(text="Symuluj")
        self.addPacketButton = Button(text="Nowy pakiet",
                                      on_press=self.on_new_packet)
        self.stepSimButton = Button(text=">|", on_press=self.on_step)
        self.playSimButton = Button(text=">")
        self.simButtonLayout = BoxLayout()
        self.sidePanelLogLayout.add_widget(self.addPacketButton)
        self.sidePanelLogLayout.add_widget(self.toggleSimButton)
        self.sidePanelLogLayout.add_widget(self.simButtonLayout)
        self.simButtonLayout.add_widget(self.playSimButton)
        self.simButtonLayout.add_widget(self.stepSimButton)

        self.packetNodes = []

        # set window color
        Window.clearcolor = (0.7, 0.7, 0.7, 1)

        super(Demoer, self).__init__(*args, **kwargs)

        self.add_widget(self.sidePanelTabbedPanel)

        # create delimiter line around the work area
        self.canvas.before.add(
            Line(rectangle=(self.workAreaXPos, self.workAreaYPos,
                            self.workAreaXDim, self.workAreaYDim),
                 width=0.5))

        # create background square behind side panel
        with self.canvas.before:
            Color(0.3, 0.3, 0.3, 1)
            Rectangle(pos=(2 * self.workAreaXPos + self.workAreaXDim, 0),
                      size=(200, 600))
            Color(1, 1, 1, 1)

    # switch between placing connection or editing nodes
    def toggleConnectionMode(self, instance):
        self.clearBubbles()
        if not self.isInConnectionMode:
            self.pendingNodeRef.background_color = (1, 0.5, 0.5, 1)
            self.isInConnectionMode = True
        else:
            self.pendingNodeRef.background_color = (1, 1, 1, 1)
            self.isInConnectionMode = False

    # display node property edit tab
    def showNodeEditPanel(self, instance):
        node_name = self.netManager.getNodeName(instance)
        self.sidePanelNodeTab.text = node_name

        if len(self.sidePanelTabbedPanel.children) == 2:
            self.sidePanelTabbedPanel.add_widget(self.sidePanelNodeTab)

        self.sidePanelTabbedPanel.switch_to(self.sidePanelNodeTab)

        self.sidePanelNodeLayout.clear_widgets()
        self.sidePanelNodeLayout.add_widget(
            Label(text="Interfejsy węzła " + node_name + ":",
                  size_hint=(1, None)))

        interfaces = self.netManager.getNodeInterfaces(instance)
        for label, (ip, conn) in interfaces.items():
            self.sidePanelNodeLayout.add_widget(
                Label(text=label, size_hint=(1, None), height=30))
            input_field = TextInput(text=ip,
                                    multiline=False,
                                    size_hint=(1, None),
                                    height=30)
            cb = functools.partial(self.on_node_edit, conn, instance)
            input_field.bind(on_text_validate=cb)
            self.sidePanelNodeLayout.add_widget(input_field)

    # remove active bubble menus
    def clearBubbles(self):
        self.remove_widget(self.nodeBubble)
        self.remove_widget(self.defaultBubble)

    def __deleteLine(self, line):
        self.canvas.before.remove(line)

    # remove active node after clicking in bubble menu
    def deleteNode(self, instance):
        self.clearBubbles()
        self.remove_widget(self.pendingNodeRef)
        self.netManager.deleteNode(self.pendingNodeRef)

        if self.sidePanelNodeTab.text == self.pendingNodeRef.children[0].text:
            self.sidePanelTabbedPanel.remove_widget(self.sidePanelNodeTab)
            self.sidePanelTabbedPanel.switch_to(self.sidePanelLogTab)

    # add pending node as computer after clicking in bubble menu
    def addComputer(self, instance):
        nodeButton = Button(pos=(self.pendingNodePosY, self.pendingNodePosX),
                            size_hint=(None, None),
                            size=(40, 40))
        nodeImg = Image(source="Images/computer.png")
        nodeLabel = Label()
        nodeButton.add_widget(nodeImg)
        nodeButton.add_widget(nodeLabel)
        nodeImg.center_x = nodeImg.parent.center_x
        nodeImg.center_y = nodeImg.parent.center_y + 10
        nodeLabel.center_x = nodeLabel.parent.center_x
        nodeLabel.center_y = nodeLabel.parent.center_y - 10
        nodeButton.bind(on_press=self.showNodeBubble)
        self.add_widget(nodeButton)
        self.netManager.addComputer(nodeButton)
        nodeLabel.text = self.netManager.getNodeName(nodeButton)

    # add pending node as router after clicking in bubble menu
    def addRouter(self, instance):
        nodeButton = Button(pos=(self.pendingNodePosY, self.pendingNodePosX),
                            size_hint=(None, None),
                            size=(40, 40))
        nodeImg = Image(source="Images/router.png")
        nodeLabel = Label()
        nodeButton.add_widget(nodeImg)
        nodeButton.add_widget(nodeLabel)
        nodeImg.center_x = nodeImg.parent.center_x
        nodeImg.center_y = nodeImg.parent.center_y + 10
        nodeLabel.center_x = nodeLabel.parent.center_x
        nodeLabel.center_y = nodeLabel.parent.center_y - 10
        nodeButton.bind(on_press=self.showNodeBubble)
        self.add_widget(nodeButton)
        self.netManager.addRouter(nodeButton)
        nodeLabel.text = self.netManager.getNodeName(nodeButton)

    # show bubble menu on click on node
    # OR create connection between active node and clicked node when in connection mode
    # OR select nodes for packet transmission
    def showNodeBubble(self, instance):
        if self.state == ToolState.SELECTING_PACKET_NODE1:
            self.packetNodes.append(instance)
            instance.background_color = (1, 0.5, 0.5, 1)
            self.state = ToolState.SELECTING_PACKET_NODE2
        elif self.state == ToolState.SELECTING_PACKET_NODE2:
            packetNodes = self.packetNodes.copy()
            packetNodes.append(instance)
            try:
                self.netManager.preparePacket(tuple(packetNodes))
            except DemoerException as e:
                self.showPopup('Error', e.message)
            else:
                instance.background_color = (1, 0.5, 0.5, 1)
                self.state = ToolState.EMPTY
                self.packetNodes.clear()
        else:
            if not self.isInConnectionMode:
                self.showNodeEditPanel(instance)
                self.clearBubbles()
                self.pendingNodeRef = instance
                self.nodeBubble.pos = (instance.pos[0] - 105,
                                       instance.pos[1] + 40)
                self.deleteNodeButton.bind(on_press=self.deleteNode)
                self.newConnButton.bind(on_press=self.toggleConnectionMode)
                self.add_widget(self.nodeBubble)
            else:
                try:
                    connection = self.netManager.addConnection(
                        instance, self.pendingNodeRef)
                except DemoerException as e:
                    self.showPopup('Error', e.message)
                else:
                    line = Line(points=[
                        self.pendingNodeRef.pos[0] + 20,
                        self.pendingNodeRef.pos[1] + 20, instance.pos[0] + 20,
                        instance.pos[1] + 20
                    ],
                                width=2)
                    self.canvas.before.add(line)
                    connection.setArg(line)
                    self.toggleConnectionMode(Button())

    # show bubble on right-clicking canvas
    def showDefaultBubble(self, posx, posy):
        self.clearBubbles()
        self.pendingNodePosY = posx - 20
        self.pendingNodePosX = posy - 20
        self.defaultBubble.pos = (posx - 125, posy)
        self.newComputerButton.bind(on_press=self.addComputer)
        self.newRouterButton.bind(on_press=self.addRouter)
        self.add_widget(self.defaultBubble)

    def animatePacket(self, sourceWidget, targetWidget):
        print('Animating')
        img = Image(source='Images/packet.png', pos=sourceWidget.pos)
        anim = Animation(x=targetWidget.pos[0], y=targetWidget.pos[1])
        self.add_widget(img)
        anim.start(img)

    def showPopup(self, title, content):
        popup = Popup(title=title,
                      content=Label(text=content),
                      size_hint=(None, None),
                      size=(500, 200))
        popup.open()

    def appendLog(self, content):
        self.logField.text = self.logField.text + content + '\n\n'

    def on_step(self, instance):
        try:
            self.netManager.stepSimulation()
        except DemoerException as e:
            self.showPopup('Error', e.message)

    def on_new_packet(self, instance):
        if not self.state == ToolState.EMPTY:
            return

        self.state = ToolState.SELECTING_PACKET_NODE1

    def on_node_edit(self, connection, node_button, text_input):
        try:
            self.netManager.setAddress(node_button, connection,
                                       text_input.text)
        except DemoerException as e:
            self.showPopup('Error', e.message)

    def on_touch_down(self, touch, after=False):
        if after:
            self.remove_widget(self.defaultBubble)
            if self.workAreaXPos + self.workAreaXDim > touch.pos[0] > self.workAreaXPos \
                    and self.workAreaYPos + self.workAreaYDim > touch.pos[1] > self.workAreaYPos:
                if touch.button == "right":
                    if self.state != ToolState.EMPTY:
                        self.state = ToolState.EMPTY
                        self.packetNodes.clear()
                    else:
                        if not self.isInConnectionMode:
                            self.showDefaultBubble(touch.x, touch.y)
                        else:
                            self.toggleConnectionMode(Button())
        else:
            Clock.schedule_once(lambda dt: self.on_touch_down(touch, True),
                                0.01)
            return super(Demoer, self).on_touch_down(touch)