Exemple #1
0
class Popup():
    "a popup"

    def __init__(self, brick, title, contentType):
        self.brick = brick
        self.title = title
        self.titleFont = Font(family='arial', size=15, bold=True)
        self.normalFont = Font(family='arial', size=13)
        self.contentType = contentType

    def open(self, position=[]):
        self.draw(position=position)

    def close(self, position):
        position.insert(0, -1)

    def draw(self):
        self.brick.screen.draw_image(9,
                                     11,
                                     'assets/graphics/misc/popup.png',
                                     transparent=Color.RED)
        self.brick.screen.set_font(self.titleFont)
        self.brick.screen.draw_text(
            self.brick.screen.width / 2 -
            self.titleFont.text_width(self.title) / 2, 15, self.title)
        self.brick.screen.draw_line(
            self.brick.screen.width / 2 -
            self.titleFont.text_width(self.title) / 2 - 1,
            31,
            self.brick.screen.width / 2 +
            self.titleFont.text_width(self.title) / 2 + 1,
            31,
            width=2)
Exemple #2
0
class UIManager:
    """
        Basicly a Menu
    """
    def __init__(self, config, settings, brick, logger, settingsPath,
                 charlieOSX):
        # general variable setup
        logger.info(self, 'Starting UI initialisation')
        self.__config = config
        self.__settings = settings
        self.__click = 'assets/media/click.wav'
        self.__confirm = 'assets/media/confirm.wav'
        self.__settingsPath = settingsPath
        self.brick = brick
        self.logger = logger
        self.os = charlieOSX
        self.profileHelper = ProfileHelper(self.logger, self.__config)
        self.__sound_lock = _thread.allocate_lock()
        self.__almostBigFont = Font(family='Arial', size=12, bold=False)
        self.__bigFont = Font(family='Arial', size=15, bold=True)
        self.position = [0, 0, False]

        # Main Menu
        self.mainMenu = Menu('sidebar')
        mainPages = [
            "assets/graphics/menus/programming.png",
            "assets/graphics/menus/testing.png",
            "assets/graphics/menus/remote.png",
            "assets/graphics/menus/competition.png",
            "assets/graphics/menus/settings.png",
        ]
        for i in range(len(mainPages)):
            name = mainPages[i].split('/')[3].split('.')[0]
            self.mainMenu.addObject(
                UIObject(name,
                         self.brick,
                         Box(0, i, 30, 25),
                         'img',
                         mainPages[i],
                         padding=(0, 0, True)))

        # Programming Menu
        self.programming = Menu('list', self.brick)
        self.programming.setList(self.__config['profileNames'])
        self.programming.setClickAction(self.runProgramming)

        # Testing Menu
        self.testing = Menu('list', self.brick)
        self.testing.setList(self.__config['profileNames'])
        self.testing.setClickAction(self.runTesting)

        # Remote-Control Menu
        self.remote = Menu('canvas')
        self.remote.addObject(
            UIObject('startButton',
                     self.brick,
                     Box(58, 80, 82, 14),
                     'textBox',
                     'Start Webremote',
                     padding=(-1, -1, False)))
        self.remote.addObject(
            UIObject('endButton',
                     self.brick,
                     Box(59, 80, 81, 14),
                     'textBox',
                     'Stop Webremote',
                     padding=(-1, -1, False),
                     visible=False))
        self.remote.getObjectByName('startButton').setClickAction(
            self.runWebremote)

        # Competition-Mode Menu
        self.competition = Menu('canvas')
        self.competition.addObject(
            UIObject('startButton',
                     self.brick,
                     Box(55, 80, 88, 14),
                     'textBox',
                     'Start Competition',
                     padding=(-1, -1, False)))
        self.competition.addObject(
            UIObject('runButton',
                     self.brick,
                     Box(74, 90, 48, 14),
                     'textBox',
                     'Start Run',
                     padding=(-1, -1, False),
                     visible=False))
        self.competition.addObject(
            UIObject('nextButton',
                     self.brick,
                     Box(72, 90, 53, 14),
                     'textBox',
                     'Start Next',
                     padding=(-1, -1, False),
                     visible=False))
        self.competition.getObjectByName('startButton').setClickAction(
            self.runCompetition)

        # Settings Menu
        self.settingsMenu = Menu('dict', self.brick)
        self.settingsMenu.setDict(self.__settings)

        # menu Variables
        self.loop = True
        self.currentMenu = self.mainMenu
        self.subMenus = [
            self.programming, self.testing, self.remote, self.competition,
            self.settingsMenu
        ]
        self.types = {
            4: 'Turn',
            5: 'Action' if not self.__config['useGearing'] else 'Gearing',
            7: 'Straight',
            9: 'Intervall',
            11: 'Curve',
            12: 'to Color',
            15: 'to Wall'
        }
        self.secondParam = {
            4: 'Angle',
            5: 'Revs',
            7: 'Distance',
            9: 'Distance',
            11: 'Distance',
            12: 'Color',
            15: 'none',
            'units': {
                4: '°',
                5: 'Revs',
                7: 'cm',
                9: 'cm',
                11: 'cm',
                12: '',
                15: ''
            }
        }
        self.thirdParam = {
            4: 'Port',
            5: 'Port',
            7: 'none' if self.__config['robotType'] != 'MECANUM' else 'Angle',
            9: 'Amount',
            11: 'Angle',
            12: 'Side',
            15: 'none',
            'units': {
                4: '',
                5: '',
                7: '°',
                9: '',
                11: '°',
                12: '',
                15: ''
            }
        }
        self.valueTypes = {
            1: {
                4: 'percentage',
                5: 'percentage',
                7: 'percentage',
                9: 'percentage',
                11: 'percentage',
                12: 'percentage',
                15: 'percentage'
            },
            2: {
                4: 'largeInt',
                5: 'largeInt',
                7: 'largeInt',
                9: 'largeInt',
                11: 'largeInt',
                12: 'bool',
                15: 'none'
            },
            3: {
                4: 'side',
                5: 'port',
                7: 'none',
                9: 'largeInt',
                11: 'largeInt',
                12: 'side',
                15: 'none'
            }
        }
        self.valueRanges = {
            'percentage': range(0, 101),
            'type': [7, 4, 5, 11, 9, 12, 15],
            'largeInt': range(0, 10000),
            'side': [2, 3, 23],
            'bool': [0, 1],
            'port': range(0, 4),
            'none': [0]
        }

        #self.logger.info(self, 'UI initialized')

    def __str__(self):
        return "UIManager"

    def __sound(self, file):
        '''
        This private method is used for playing a sound in a separate thread so that other code can be executed simultaneously.

        Args:
            file (str / SoundFile): The path to the soundfile to play
        '''
        def __playSoundFile(soundFile):
            with self.__sound_lock:
                self.brick.speaker.play_file(soundFile)

        _thread.start_new_thread(__playSoundFile, (file, ))

    def mainLoop(self):
        # Welcome screen
        self.brick.screen.draw_image(0,
                                     0,
                                     'assets/graphics/menus/mainMenu.png',
                                     transparent=Color.RED)
        while not any(self.brick.buttons.pressed()):
            pass
        if Button.UP in self.brick.buttons.pressed():
            self.position[1] = self.currentMenu.maxY
        elif Button.DOWN in self.brick.buttons.pressed():
            self.position[1] = 0
        self.currentMenu.draw(self.position)
        print(self.position)
        time.sleep(0.3)
        self.menuLocations = [
            "assets/graphics/animations/mainProgram/10.png",
            "assets/graphics/animations/mainTest/10.png",
            "assets/graphics/animations/mainRemote/10.png",
            "assets/graphics/animations/mainCompetition/10.png",
            "assets/graphics/animations/mainSettings/10.png",
        ]

        while self.loop:
            if any(self.brick.buttons.pressed()):
                if Button.UP in self.brick.buttons.pressed(
                ) and not self.position[2]:
                    self.position[1] = self.position[1] - 1 if self.position[
                        1] > 0 else self.currentMenu.maxY
                elif Button.DOWN in self.brick.buttons.pressed(
                ) and not self.position[2]:
                    self.position[1] = self.position[1] + 1 if self.position[
                        1] < self.currentMenu.maxY else 0
                elif Button.LEFT in self.brick.buttons.pressed() and len(
                        self.position) > 3 and not self.position[2]:
                    if self.currentMenu.getType(
                    ) == 'canvas' and self.position[0] > 0:
                        self.position[
                            0] = self.position[0] - 1 if self.position[
                                0] > 0 else self.currentMenu.maxX
                    else:
                        self.position.pop(0)
                        self.position.pop(0)
                        self.position.pop(0)
                        if len(self.position) == 3:
                            self.animate(self.position[1], False)
                            self.currentMenu = self.mainMenu
                elif Button.RIGHT in self.brick.buttons.pressed(
                ) and not self.position[2]:
                    # self.position[0] = self.position[0] + 1 if self.position[0] < self.currentMenu.maxX else 0
                    if self.currentMenu.getType() == 'canvas':
                        self.position[
                            0] = self.position[0] + 1 if self.position[
                                0] < self.currentMenu.maxX else 0
                    else:
                        if len(self.position) == 3:
                            self.animate(self.position[1], True)
                            self.currentMenu = self.subMenus[self.position[1]]
                        self.position.insert(0, False)
                        self.position.insert(0, 0)
                        self.position.insert(0, 0)
                elif Button.RIGHT in self.brick.buttons.pressed(
                ) and self.position[2]:
                    self.position[0] = self.position[0] + 1 if self.position[
                        0] < self.currentMenu.maxX else 0
                    self.__settings['options'][list(
                        self.__settings['options'].keys())[
                            self.position[1]]] = self.position[0]
                elif Button.LEFT in self.brick.buttons.pressed(
                ) and self.position[2]:
                    self.position[0] = self.position[0] - 1 if self.position[
                        0] > 0 else self.currentMenu.maxX
                    self.__settings['options'][list(
                        self.__settings['options'].keys())[
                            self.position[1]]] = self.position[0]
                elif Button.CENTER in self.brick.buttons.pressed():
                    if self.currentMenu.getType() == 'list':
                        self.currentMenu.click(self.position)
                    elif self.currentMenu.getType() == 'dict':
                        if self.position[2]:
                            self.position.pop(0)
                            self.position.pop(0)
                            self.position.pop(0)
                            self.position[2] = not self.position[2]
                            self.os.storeSettings(self.__settings, 'default')
                            self.os.applySettings(self.__settings)
                        else:
                            self.position[2] = not self.position[2]
                            self.position.insert(0, True)
                            self.position.insert(0, self.position[2])
                            self.position.insert(
                                0, self.__settings['options'][list(
                                    self.__settings['options'].keys())[
                                        self.position[0]]])
                    elif len(self.position) != 3:
                        self.position[2] = not self.position[2]
                        self.currentMenu.getObjectByPostion(
                            self.position).click()
                        if self.currentMenu.getType() not in ['canvas']:
                            self.position.insert(0, False)
                            self.position.insert(0, 0)
                            self.position.insert(0, 0)
                if self.position[0] == -1:
                    self.position.pop(0)
                    self.brick.screen.draw_image(
                        0,
                        0,
                        self.menuLocations[self.position[len(self.position) -
                                                         4]],
                        transparent=Color.RED)
                self.currentMenu.draw(self.position)
                print(self.position)
                time.sleep(0.3)

    def animate(self, state, direction):
        '''
        Animates the transition between the main-menu-pages and the submenu-pages
        Args:
            state (int): The menu-transition to animate
            direction (bool): wether it should play the animation forwards or backwards
        '''
        menus = [
            'mainProgram', 'mainTest', 'mainRemote', 'mainCompetition',
            'mainSettings'
        ]
        if direction:
            try:
                for i in range(1, 11):
                    self.brick.screen.draw_image(
                        0,
                        0,
                        'assets/graphics/animations/%s/%s.png' %
                        (menus[state], i),
                        transparent=Color.RED)
                    time.sleep(0.05)
            except Exception as exception:
                self.logger.error(self, "Could not animate menu: ",
                                  str(exception))
        else:
            try:
                for i in reversed(range(1, 11)):
                    self.brick.screen.draw_image(
                        0,
                        0,
                        'assets/graphics/animations/%s/%s.png' %
                        (menus[state], i),
                        transparent=Color.RED)
                    time.sleep(0.05)
            except Exception as exception:
                self.logger.error(self, "Could not animate menu: ",
                                  str(exception))

    def runProgramming(self, position):
        index = position[1]
        content = self.profileHelper.getProfileData(
            self.__config['profileNames'][index])

        self.runList = Menu('progList', self.brick)
        self.runList.setList(content)
        self.runList.setClickAction(self.runEditing)
        self.runList.draw(self.position)

        # sideloop for interactive sub submenu
        while not Button.LEFT in self.brick.buttons.pressed():
            if any(self.brick.buttons.pressed()):
                if Button.UP in self.brick.buttons.pressed(
                ) and not self.position[2]:
                    self.position[1] = self.position[1] - 1 if self.position[
                        1] > 0 else self.runList.maxY
                elif Button.DOWN in self.brick.buttons.pressed(
                ) and not self.position[2]:
                    self.position[1] = self.position[1] + 1 if self.position[
                        1] < self.runList.maxY else 0
                elif Button.CENTER in self.brick.buttons.pressed():
                    startTime = time.time()
                    deleted = False
                    while Button.CENTER in self.brick.buttons.pressed():
                        if time.time() - startTime > 2 and not deleted:
                            deleted = True
                            content.pop()
                            content.pop(self.position[1])
                            self.runList.setList(content)
                            self.runList.draw(self.position)
                            self.brick.speaker.beep()

                    buttonTime = time.time() - startTime
                    if buttonTime < 2:  # edit step
                        if self.position[1] != len(content) - 1:
                            self.runList.click(self.position)
                        else:
                            content.pop()
                            content.append([7, 100, 10, 0])
                            self.runList.setList(content)
                            self.profileHelper.setProfileData(
                                self.__config['profileNames'][index], content)

                if self.position[0] == -1:
                    self.position.pop(0)
                    self.brick.screen.draw_image(
                        0,
                        0,
                        self.menuLocations[self.position[len(self.position) -
                                                         4]],
                        transparent=Color.RED)
                print(self.position, content)
                self.runList.draw(self.position)
                time.sleep(0.3)

    def runEditing(self, position):
        def formatScreenContent(thirdType):
            screenContent[0] = 'Type: %s' % self.types[content[index][0]]
            screenContent[1] = 'Speed: %s%%' % content[index][1]
            screenContent[2] = '%s: %s%s' % (
                self.secondParam[content[index][0]], content[index][2],
                self.secondParam['units'][content[index][0]]
            ) if self.secondParam[content[index][0]] != 'none' else ''
            value = str(content[index][3]).replace('23', 'Left/Right').replace(
                '2', 'Left').replace(
                    '3', 'Right') if thirdType == 'side' else content[index][3]
            screenContent[3] = '%s: %s%s' % (
                self.thirdParam[content[index][0]], value,
                self.thirdParam['units'][content[index][0]]
            ) if self.thirdParam[content[index][0]] != 'none' else ''

        smallStep = 1
        bigStep = 5
        index = position[1]
        screenContent = ['', '', '', '']
        content = self.profileHelper.getProfileData(
            self.__config['profileNames'][position[4]])

        formatScreenContent(self.valueTypes[3][content[index][0]])

        menu = ProgrammingWindow(self.brick, 'Edit Step', 'list',
                                 screenContent)
        self.position.insert(0, False)
        self.position.insert(0, 0)
        self.position.insert(0, 0)
        mmax = 3
        menu.open(position)
        while not (Button.LEFT in self.brick.buttons.pressed()
                   and not position[2]):
            if any(self.brick.buttons.pressed()):
                valueType = self.valueTypes[position[1]][
                    content[index][0]] if position[1] != 0 else 'type'
                valueRange = self.valueRanges[valueType]
                if Button.UP in self.brick.buttons.pressed():
                    if self.position[2]:
                        if valueType not in ['type', 'side']:
                            content[index][position[1]] = content[index][position[
                                1]] + smallStep if content[index][position[
                                    1]] + smallStep in valueRange else valueRange[
                                        0]
                        else:
                            try:
                                content[index][position[1]] = valueRange[
                                    valueRange.
                                    index(content[index][position[1]]) -
                                    1 if valueRange.
                                    index(content[index][position[1]]) -
                                    1 >= 0 else len(valueRange) - 1]
                            except ValueError:
                                content[index][position[1]] = valueRange[0]
                    else:
                        self.position[1] = self.position[
                            1] - 1 if self.position[1] > 0 else mmax
                elif Button.DOWN in self.brick.buttons.pressed():
                    if self.position[2]:
                        if valueType not in ['type', 'side']:
                            content[index][position[1]] = content[index][position[
                                1]] - smallStep if content[index][position[
                                    1]] - smallStep in valueRange else valueRange[
                                        len(valueRange) - 1]
                        else:
                            try:
                                content[index][position[1]] = valueRange[
                                    valueRange.
                                    index(content[index][position[1]]) +
                                    1 if valueRange.
                                    index(content[index][position[1]]) +
                                    1 < len(valueRange) else 0]
                            except ValueError:
                                content[index][position[1]] = valueRange[0]
                    else:
                        self.position[1] = self.position[
                            1] + 1 if self.position[1] < mmax else 0
                elif Button.RIGHT in self.brick.buttons.pressed():
                    if self.position[2]:
                        if valueType not in ['type', 'side']:
                            content[index][position[1]] = content[index][
                                position[1]] + bigStep if content[index][position[
                                    1]] + bigStep in valueRange else valueRange[
                                        0]
                elif Button.LEFT in self.brick.buttons.pressed():
                    if self.position[2]:
                        if valueType not in ['type', 'side']:
                            content[index][position[1]] = content[index][
                                position[1]] - bigStep if content[index][position[
                                    1]] - bigStep in valueRange else valueRange[
                                        len(valueRange) - 1]
                elif Button.CENTER in self.brick.buttons.pressed():
                    position[2] = not position[2]
                formatScreenContent(self.valueTypes[3][content[index][0]])
                menu.updateContent(screenContent)
                menu.draw(position=position)
                if not (Button.LEFT in self.brick.buttons.pressed()
                        and not position[2]):
                    time.sleep(0.3)

        self.position.pop(0)
        self.position.pop(0)
        self.position.pop(0)
        self.profileHelper.setProfileData(
            self.__config['profileNames'][position[4]], content)
        menu.close(position)
        time.sleep(0.3)

    def runTesting(self, position):
        index = position[1]
        profileData = self.profileHelper.getProfileData(
            self.__config['profileNames'][index])
        time.sleep(0.3)
        self.os.robot.execute(profileData)

    def runWebremote(self):
        self.currentMenu.getObjectByName('startButton').setVisibility(False)
        self.currentMenu.getObjectByName('endButton').setVisibility(True)
        self.position[1] += 1
        self.currentMenu.draw(self.position)
        time.sleep(0.3)
        self.os.webremote.run()
        self.currentMenu.getObjectByName('startButton').setVisibility(True)
        self.currentMenu.getObjectByName('endButton').setVisibility(False)
        self.position[2] = False
        self.position[1] -= 1
        self.currentMenu.draw(self.position)
        time.sleep(0.3)

    def runCompetition(self):
        dataArray = []
        self.wireless(
            False
        )  # uncomment to not loose connectivity for console-logging and effective development through wifi
        self.currentMenu.getObjectByName('startButton').setVisibility(False)
        self.currentMenu.getObjectByName('runButton').setVisibility(True)
        self.position[0], self.position[1] = 1, 1
        self.currentMenu.draw(self.position)
        for i in self.__config['profileNames']:
            dataArray.append(self.profileHelper.getProfileData(i))
        self.currentMenu.getObjectByName('runButton').setVisibility(False)
        self.currentMenu.getObjectByName('nextButton').setVisibility(True)
        time.sleep(0.3)
        for index in range(0, len(dataArray)):
            self.brick.screen.draw_box(30,
                                       30,
                                       200,
                                       80,
                                       fill=True,
                                       color=Color.WHITE)
            self.brick.screen.set_font(self.__almostBigFont)
            self.brick.screen.draw_text(74,
                                        36,
                                        "Run %s/%s:" %
                                        (index, len(dataArray) - 1),
                                        background_color=Color.WHITE)
            self.brick.screen.set_font(self.__bigFont)
            self.brick.screen.draw_text(98 - self.__bigFont.text_width(
                self.__config['profileNames'][index]) / 2,
                                        60,
                                        self.__config['profileNames'][index],
                                        background_color=Color.WHITE)
            while Button.CENTER not in self.brick.buttons.pressed():
                pass
            self.position[0], self.position[1] = 1, 1
            self.currentMenu.draw(self.position)
            time.sleep(0.3)
            self.os.robot.execute(dataArray[index])
            time.sleep(0.3)
            self.position[0], self.position[1] = 1, 0
            self.currentMenu.draw(self.position)

        self.wireless(True)
        self.brick.screen.draw_box(30,
                                   30,
                                   200,
                                   80,
                                   fill=True,
                                   color=Color.WHITE)
        self.position[0], self.position[1], self.position[2] = 0, 0, False
        self.currentMenu.getObjectByName('startButton').setVisibility(True)
        self.currentMenu.getObjectByName('runButton').setVisibility(False)
        self.currentMenu.getObjectByName('nextButton').setVisibility(False)
        self.currentMenu.draw(self.position)

    def wireless(self, enable):
        cmd = 'enable' if not enable else 'disable'
        os.system('connmanctl {} offline'.format(cmd))
Exemple #3
0
    def error(self, method, msg, exception):
        '''
        This method formats the given inputs as <[time] [MethodName] [Wrror] msg>.
        The output of this fuction can be disabled by setting the "Logging-Level" in the settings to 4 or higher.
        Also dependent on wether or not "Show Errors" is disabled or not in the settings,
        this function will create a 'popup' on-screen with the given warn-message.

        Args:
            method (obj): A passthrough of the object calling this fuction
            msg (str): The error message
            exception (exception / str): string or exception of the error that occured
        '''
        if self.__settings['options']['Logging-level'] <= 3:
            print(
                self.getFormattedTime(), '[%s] [Error] %s: %s: %s' %
                (str(method), msg, type(exception).__name__, str(exception)))
            self.__logFile.write('%s [%s] [Error] %s: %s: %s\n' %
                                 (self.getFormattedTime(), str(method), msg,
                                  type(exception).__name__, str(exception)))

        if self.__settings['options']['Show Errors']:
            exception = str(exception)
            self.__sound(SoundFile.GENERAL_ALERT)
            self.__brick.screen.draw_image(
                26,
                24,
                'assets/graphics/notifications/error.png',
                transparent=Color.RED)
            self.__brick.screen.set_font(Font(family='arial', size=7))
            if Font.text_width(Font(family='arial', size=7), exception) <= 90:
                self.__brick.screen.draw_text(32,
                                              47,
                                              exception,
                                              text_color=Color.BLACK)
            elif len(exception) <= 30 * 2:
                exception1, exception2 = exception[:27], exception[27:]
                self.__brick.screen.draw_text(32,
                                              47,
                                              exception1,
                                              text_color=Color.BLACK)
                self.__brick.screen.draw_text(32,
                                              57,
                                              exception2,
                                              text_color=Color.BLACK)
            else:
                exception1, exception2, exception3 = exception[:27], exception[
                    27:53], exception[53:]
                self.__brick.screen.draw_text(32,
                                              47,
                                              exception1,
                                              text_color=Color.BLACK)
                self.__brick.screen.draw_text(32,
                                              57,
                                              exception2,
                                              text_color=Color.BLACK)
                self.__brick.screen.draw_text(32,
                                              67,
                                              exception3,
                                              text_color=Color.BLACK)

            #wait for user to press middle button
            while not Button.CENTER in self.__brick.buttons.pressed():
                pass
            self.__brick.screen.draw_image(
                26,
                24,
                'assets/graphics/notifications/errorSel.png',
                transparent=Color.RED)
            #wait for user letting button go
            while Button.CENTER in self.__brick.buttons.pressed():
                pass
            self.__refreshScreenNeeded = 1
Exemple #4
0
    def warn(self, method, msg):
        '''
        This method formats the given inputs as <[time] [MethodName] [Warn] msg>.
        The output of this fuction can be disabled by setting the "Logging-Level" in the settings to 3 or higher.
        Also dependent on wether or not "Show Warnings" is disabled or not in the settings,
        this function will create a 'popup' on-screen with the given warn-message.

        Args:
            method (obj): A passthrough of the object calling this fuction
            msg (str): The warn message
        '''
        if self.__settings['options']['Logging-level'] <= 2:
            print(self.getFormattedTime(), '[%s] [Warning]' % str(method), msg)
            self.__logFile.write('%s [%s] [Warning] %s\n' %
                                 (self.getFormattedTime(), str(method), msg))

        if self.__settings['options']['Show Warnings']:
            self.__sound(SoundFile.GENERAL_ALERT)
            self.__brick.screen.draw_image(
                26,
                24,
                'assets/graphics/notifications/warn.png',
                transparent=Color.RED)
            self.__brick.screen.draw_text(31, 34, msg, text_color=Color.BLACK)

            if Font.text_width(Font(family='arial', size=7), exception) <= 90:
                self.__brick.screen.draw_text(32,
                                              47,
                                              msg,
                                              text_color=Color.BLACK)
            elif len(exception) <= 30 * 2:
                msg1, msg2 = msg[:27], msg[27:]
                self.__brick.screen.draw_text(32,
                                              47,
                                              msg1,
                                              text_color=Color.BLACK)
                self.__brick.screen.draw_text(32,
                                              57,
                                              msg2,
                                              text_color=Color.BLACK)
            else:
                msg1, msg2, msg3 = exception[:27], exception[27:53], exception[
                    53:]
                self.__brick.screen.draw_text(32,
                                              47,
                                              msg1,
                                              text_color=Color.BLACK)
                self.__brick.screen.draw_text(32,
                                              57,
                                              msg2,
                                              text_color=Color.BLACK)
                self.__brick.screen.draw_text(32,
                                              67,
                                              msg3,
                                              text_color=Color.BLACK)

            #wait for user to press middle button
            while not Button.CENTER in self.__brick.buttons.pressed():
                pass
            self.__brick.screen.draw_image(
                26,
                24,
                'assets/graphics/notifications/warnSel.png',
                transparent=Color.RED)
            #wait for user letting button go
            while Button.CENTER in self.__brick.buttons.pressed():
                pass
            self.__refreshScreenNeeded = 1