Beispiel #1
0
    def _convert_animation_value_to_float(self, prop: str,
                                          val: Union[str, int, float], event_args) -> Union[float, int]:
        """
        Convert an animation property value to a numeric value.
        Args:
            prop: The name of the property to animate
            val: The animation target value (may be a string that contains a % sign)

        Returns:
            Numeric value (float or int).
        """
        if val.startswith("(") and val.endswith(")"):
            try:
                val = event_args[val[1:-1]]
            except KeyError:
                raise AssertionError("Excepted an event parameter {}".format(val[1:-1]))

        try:
            val = percent_to_float(val, self._percent_prop_dicts[prop])
        except KeyError:
            # because widget properties can include a % sign, they are
            # all strings, so even ones that aren't on the list to look
            # for percent signs have to be converted to numbers.
            if '.' in val:
                val = float(val)
            else:
                val = int(val)

        return val
Beispiel #2
0
    def build_animation_from_config(self, config_list):
        """Build animation object from config."""
        if not isinstance(config_list, list):
            raise TypeError('build_animation_from_config requires a list')

        # find any named animations and replace them with the real ones
        animation_list = list()

        for entry in config_list:
            if 'named_animation' in entry:
                for named_anim_settings in (
                        self.mc.animations[entry['named_animation']]):
                    animation_list.append(named_anim_settings)
            else:
                animation_list.append(entry)

        final_anim = None
        repeat = False

        for settings in animation_list:
            prop_dict = dict()
            for prop, val in zip(settings['property'], settings['value']):
                try:
                    val = percent_to_float(val, self._percent_prop_dicts[prop])
                except KeyError:
                    # because widget properties can include a % sign, they are
                    # all strings, so even ones that aren't on the list to look
                    # for percent signs have to be converted to numbers.
                    if '.' in val:
                        val = float(val)
                    else:
                        val = int(val)

                prop_dict[prop] = val

                if prop not in self._pre_animated_settings:
                    self._pre_animated_settings[prop] = getattr(self, prop)

            anim = Animation(duration=settings['duration'],
                             transition=settings['easing'],
                             **prop_dict)

            if not final_anim:
                final_anim = anim
            elif settings['timing'] == 'with_previous':
                final_anim &= anim
            elif settings['timing'] == 'after_previous':
                final_anim += anim

            if settings['repeat']:
                repeat = True

        if repeat:
            final_anim.repeat = True

        return final_anim
Beispiel #3
0
    def _calculate_y_position(
            parent_h: int,
            y: Optional[Union[int, str]] = None,
            round_y: Optional[Union[bool, str]] = None) -> float:
        # Set defaults
        if y is None:
            y = 'middle'

        # --------------------
        # Y / height / vertical
        # --------------------

        # Calculate position
        if isinstance(y, str):

            y = str(y).replace(' ', '')
            start_y = 0

            if y.startswith('top'):
                y = y.strip('top')
                start_y = parent_h

            elif y.startswith('middle'):
                y = y.strip('middle')
                start_y = parent_h / 2

            elif y.startswith('center'):
                y = y.strip('center')
                start_y = parent_h / 2

            elif y.startswith('bottom'):
                y = y.strip('bottom')

            if not y:
                y = '0'

            y = percent_to_float(y, parent_h)
            y += start_y

            if round_y == 'bottom':
                y = math.floor(y)
            elif round_y == 'top':
                y = math.ceil(y)

        return y
Beispiel #4
0
    def _calculate_x_position(
            parent_w: int,
            x: Optional[Union[int, str]] = None,
            round_x: Optional[Union[bool, str]] = None) -> float:
        # ----------------------
        # X / width / horizontal
        # ----------------------
        if x is None:
            x = 'center'
        # Calculate position
        if isinstance(x, str):

            x = str(x).replace(' ', '')
            start_x = 0

            if x.startswith('right'):
                x = x.strip('right')
                start_x = parent_w

            elif x.startswith('middle'):
                x = x.strip('middle')
                start_x = parent_w / 2

            elif x.startswith('center'):
                x = x.strip('center')
                start_x = parent_w / 2

            elif x.startswith('left'):
                x = x.strip('left')

            if not x:
                x = '0'

            x = percent_to_float(x, parent_w)
            x += start_x

            if round_x == 'left':
                x = math.floor(x)
            elif round_x == 'right':
                x = math.ceil(x)

        return x
Beispiel #5
0
    def _convert_animation_value_to_float(
            self, prop: str, val: Union[str, int, float]) -> Union[float, int]:
        """
        Convert an animation property value to a numeric value.
        Args:
            prop: The name of the property to animate
            val: The animation target value (may be a string that contains a % sign)

        Returns:
            Numeric value (float or int).
        """
        try:
            val = percent_to_float(val, self._percent_prop_dicts[prop])
        except KeyError:
            # because widget properties can include a % sign, they are
            # all strings, so even ones that aren't on the list to look
            # for percent signs have to be converted to numbers.
            if '.' in val:
                val = float(val)
            else:
                val = int(val)

        return val
Beispiel #6
0
    def test_percent_to_float(self):
        num = 1
        total = 1
        self.assertEqual(percent_to_float(num, total), 1.0)

        num = 1
        total = 2
        self.assertEqual(percent_to_float(num, total), 1.0)

        num = 0
        total = 2
        self.assertEqual(percent_to_float(num, total), 0.0)

        num = '1'
        total = 1
        self.assertEqual(percent_to_float(num, total), 1.0)

        num = '1'
        total = 2
        self.assertEqual(percent_to_float(num, total), 1.0)

        num = '0'
        total = 2
        self.assertEqual(percent_to_float(num, total), 0.0)

        num = '100%'
        total = 1
        self.assertEqual(percent_to_float(num, total), 1.0)

        num = '100%'
        total = 2
        self.assertEqual(percent_to_float(num, total), 2.0)

        num = '0%'
        total = 2
        self.assertEqual(percent_to_float(num, total), 0.0)

        num = '25%'
        total = 800
        self.assertEqual(percent_to_float(num, total), 200.0)

        num = '200%'
        total = 1
        self.assertEqual(percent_to_float(num, total), 2.0)
Beispiel #7
0
    def calculate_initial_position(
            parent_w: int,
            parent_h: int,
            x: Optional[Union[int, str]] = None,
            y: Optional[Union[int, str]] = None,
            round_x: Optional[Union[bool, str]] = None,
            round_y: Optional[Union[bool, str]] = None) -> tuple:
        """Returns the initial x,y position for the widget within a larger
        parent frame based on several positioning parameters. This position will
        be combined with the widget anchor position to determine its actual
        position on the screen.

        Args:
            parent_w: Width of the parent frame.
            parent_h: Height of the parent frame.
            x: (Optional) Specifies the x (horizontal) position of the widget from
                the left edge of the slide. Can be a numeric value which
                represents the actual x value, or can be a percentage (string with
                percent sign, like '20%') which is set taking into account the size
                of the parent width. (e.g. parent width of 800 with x='20%'
                results in x=160. Can also be negative to position the widget
                partially off the left of the slide. Default value of None will
                return the horizontal center (parent width / 2). Can also start
                with the strings "left", "center", or "right" which can be combined
                with values. (e.g right-2, left+4, center-1)
            y: (Optional) Specifies the y (vertical) position of the widget from
                the bottom edge of the slide. Can be a numeric value which
                represents the actual y value, or can be a percentage (string with
                percent sign, like '20%') which is set taking into account the size
                of the parent height. (e.g. parent height of 600 with y='20%'
                results in y=120. Can also be negative to position the widget
                partially off the bottom of the slide. Default value of None will
                return the vertical center (parent height / 2). Can also start
                with the strings "top", "middle", or "bottom" which can be combined
                with values. (e.g top-2, bottom+4, middle-1)
            round_x: (Optional) Specifies a direction of either "left" or "right"
                to round the calculated pixel value for the horizontal position.
                Used to prevent partial pixel placement on DMDs, especially when
                position/anchors are specified in percentages
            round_y: (Optional) Specifies a direction of either "bottom" or "top"
                to round the calculated pixel value for the vertical position.
                Used to prevent partial pixel placement on DMDs, especially when
                position/anchors are specified in percentages

        Returns: Tuple of x, y coordinates for the lower-left corner of the
            widget you're placing.

        See the widgets documentation for examples.

        """
        # Set defaults
        if x is None:
            x = 'center'
        if y is None:
            y = 'middle'

        # ----------------------
        # X / width / horizontal
        # ----------------------

        # Set position
        if isinstance(x, str):

            x = str(x).replace(' ', '')
            start_x = 0

            if x.startswith('right'):
                x = x.strip('right')
                start_x = parent_w

            elif x.startswith('middle'):
                x = x.strip('middle')
                start_x = parent_w / 2

            elif x.startswith('center'):
                x = x.strip('center')
                start_x = parent_w / 2

            elif x.startswith('left'):
                x = x.strip('left')

            if not x:
                x = '0'

            x = percent_to_float(x, parent_w)
            x += start_x

            if round_x == 'left':
                x = math.floor(x)
            elif round_x == 'right':
                x = math.ceil(x)

        # --------------------
        # Y / height / vertical
        # --------------------

        # Set position
        if isinstance(y, str):

            y = str(y).replace(' ', '')
            start_y = 0

            if y.startswith('top'):
                y = y.strip('top')
                start_y = parent_h

            elif y.startswith('middle'):
                y = y.strip('middle')
                start_y = parent_h / 2

            elif y.startswith('center'):
                y = y.strip('center')
                start_y = parent_h / 2

            elif y.startswith('bottom'):
                y = y.strip('bottom')

            if not y:
                y = '0'

            y = percent_to_float(y, parent_h)
            y += start_y

            if round_y == 'bottom':
                y = math.floor(y)
            elif round_y == 'top':
                y = math.ceil(y)

        return x, y