Exemplo n.º 1
0
class Pair():
    """
        This class represents a binary tree. This tree is meant to be as follow:
                        pair
                pair            pair
            pair    pair    pair    pair
                        etc.
          id  id  id   id  id  id  id  id

        The value of each pair is a splitter which its parent is the splitter of the parent pair.
    """
    def __init__(self, left=None, right=None, value=None):

        # The value of the current pair.
        self.value = value

        # The parent of the current pair.
        self.parent = None

        # The left element of the pair.
        self.left = left

        # The right element of the pair.
        self.right = right

    def create_tree(self, ids):
        """
            The Recursion converts the received ids list to a tree.
        """

        if len(ids) > 2:

            self.left = Pair()
            self.right = Pair()

            max_power = Pair.get_max_power(2, len(ids))

            ids_buffer = Pair.get_by_half(max_power, len(ids))

            if ids_buffer > len(ids) / 2.0:

                ids_buffer = len(ids) - ids_buffer

            if ids_buffer <= 1:
                self.left.create_tree([ids[0]])
            else:
                self.left.create_tree(ids[:ids_buffer])

            if len(ids) - ids_buffer <= 1:
                self.right.create_tree([ids[-1]])
            else:
                self.right.create_tree(ids[ids_buffer:])

        elif len(ids) == 2:

            self.left = Pair(value=ids[0])
            self.right = Pair(value=ids[1])

        elif len(ids) == 1:

            self.left = Pair(value=ids[0])
            self.right = None

    def vlr(self, monitors_dict=None, recorder=None):
        """
            A recursion on the current tree of the form: value, left, right. This recursion creates the splitters and
            the monitors in the tree.
        """

        # It's not a monitor, it's a splitter.
        if not self.value:

            # In case it's the root of the tree set the parent panel of the splitter to the parent of the root. It
            # doesn't have value attribute like a pair instance.
            if not isinstance(self.parent, Pair):

                # True if there is only one monitor in the whole tree.
                if not self.right:

                    # Extract the id of the monitor in the left element of the pair.
                    monitor_id = self.left.value

                    # Convert this pair to a monitor.
                    self.value = Monitor(self.parent, monitor_id)

                    # Both its elements should be None.
                    self.left = None

                    # Update the monitor as described in the function.
                    self.value.update_monitor(recorder, monitors_dict)

                else:

                    # Create the splitter.
                    self.value = wx.SplitterWindow(self.parent,
                                                   style=wx.SP_LIVE_UPDATE)

                    # Set the minimum size of the splitter's panels so the wouldn't be too small.
                    self.value.SetMinimumPaneSize(50)

            # It's not the first pair in the tree.
            else:

                # This pair instance has only one monitor. Therefore it shouldn't be a splitter. Convert this pair to
                # its left pair object.
                if not self.right:

                    # Convert this pair to a monitor.
                    self.value = Monitor(self.parent.value, self.left.value)

                    # Both its elements should be None.
                    self.left = None

                    # Update the monitor as described in the function.
                    self.value.update_monitor(recorder, monitors_dict)

                # It's a regular splitter.
                else:

                    # Create the splitter.
                    self.value = wx.SplitterWindow(self.parent.value,
                                                   style=wx.SP_LIVE_UPDATE)

                    # Set the minimum size of the splitter's panels so the wouldn't be too small.
                    self.value.SetMinimumPaneSize(50)

                # Create a sizer.
                sizer = wx.BoxSizer(wx.VERTICAL)

                # Add the splitter / monitor to the sizer.
                sizer.Add(self.value, 1, wx.EXPAND)

                # Set the sizer as the parent's sizer.
                self.parent.value.SetSizer(sizer)

            # Keep iterating on the left pair of the current pair.
            if self.left:

                self.left.parent = self
                self.left.vlr(monitors_dict, recorder)

            # Keep iterating on the right pair of the current pair.
            if self.right:

                self.right.parent = self
                self.right.vlr(monitors_dict, recorder)

        # It's a monitor (of a splitter), the lowest pair in the tree.
        else:

            # Create the monitor.
            self.value = Monitor(self.parent.value, self.value)

            # Create a sizer.
            sizer = wx.BoxSizer(wx.VERTICAL)

            # Add the monitor to the sizer.
            sizer.Add(self.value, 1, wx.EXPAND)

            # Set the sizer as the parent's sizer.
            self.parent.value.SetSizer(sizer)

            # Update the monitor as described in the function.
            self.value.update_monitor(recorder, monitors_dict)

    def lrv(self, flag):
        """
            A recursion on the current tree of the form: left, right, value. This recursion split the splitters. The
            flag parameter is for determining weather there is a need for a horizontal split or a vertical one.
        """

        if self.left:

            self.left.lrv(not flag)

        if self.right:

            self.right.lrv(not flag)

        # Split only if there are two elements for the current pair instance.
        if self.left and self.right:

            if flag:

                self.value.SplitHorizontally(self.left.value, self.right.value)

            else:

                self.value.SplitVertically(self.left.value, self.right.value)

    @staticmethod
    def get_max_power(base, number):
        """
            This function receives a base of a power and a number. The function the calculates what is the highest power
            that its result is less than the received number. This function doesn't handle usage of number < 1, i.e.
            the smallest base that can be returned is 0.
        """

        if (number**0.5 - floor(number**0.5)) == 0 or number == 2:
            return number

        current_power = 1

        while True:

            if base**current_power > number:

                return base**(current_power - 1)

            else:

                current_power += 1

    @staticmethod
    def get_by_half(max_power, number):
        """
            The function receives a power and its max power by base 2. Returns the right ids_buffer value.
        """

        if max_power * 1.5 > number:

            return max_power / 2

        return max_power