Exemplo n.º 1
0
    def __init__(self, pydisplay, event_handler):
        super().__init__(pydisplay, event_handler, "Buttons", (400, 300),
                         Colors.BLACK)

        self.button = Drawables.Button(50,
                                       50,
                                       100,
                                       50,
                                       "Hello",
                                       25,
                                       Colors.WHITE,
                                       Colors.BLUE,
                                       callback=self.button_callback)
        self.textBox = Drawables.Text(50,
                                      110,
                                      "textbox here",
                                      15,
                                      Colors.RED,
                                      Drawables.Text.ALIGN_X_CENTER,
                                      Drawables.Text.ALIGN_Y_CENTER,
                                      rotate=90)
        self.textBox2 = Drawables.Text(200, 100, "textbox here", 15,
                                       Colors.WHITE,
                                       Drawables.Text.ALIGN_X_RIGHT,
                                       Drawables.Text.ALIGN_Y_TOP)
        self._drawables.append(self.button)
        self._drawables.append(self.textBox)
        self._drawables.append(self.textBox2)

        self._event_handler.register_event(object,
                                           Events.EventTypes.BUTTON_HOLD,
                                           self.button_27_callback)
Exemplo n.º 2
0
 def set_y_label(self,
                 text,
                 distance_from_left_of_graph=5,
                 font_size=15,
                 fg_color=None):
     """
     Set the y label (this will be rotated and centered on the left of the chart)
     :param text: Text to display
     :param distance_from_left_of_graph: Distance top of text (upward direction of letters) is from left of graph
     :param font_size: Font size
     :param fg_color: Font color
     :return: None
     """
     x = self.x + distance_from_left_of_graph
     y = self.y + self._plot["offset_y"] + self._plot["height"] / 2
     fg_color = self._plot["fg_color"] if fg_color is None else fg_color
     self._drawables["y_label"] = Drawables.Text(
         x=x,
         y=y,
         text=text,
         font_size=font_size,
         fg_color=fg_color,
         align_x=Drawables.Text.ALIGN_X_LEFT,
         align_y=Drawables.Text.ALIGN_Y_CENTER,
         rotate=90)
Exemplo n.º 3
0
    def __init__(self, event_handler, pages, switcher_location):
        """
        This is the module that manages the pages.  This allows support for multiple pages and has the logic for
        switching between pages.  You do not need to directly create an instance of this because PyDisplay creates it
        automatically.
        :param event_handler: Event handler (needs to register events for the switcher)
        :param pages: A list of page instances (must have at least one page)
        :param switcher_location: Where to put the switcher?  Refer to SWITCHER_LOCATIONS for options
        """
        assert isinstance(event_handler, Events.EventHandler)
        assert isinstance(pages, list) and len(pages) >= 1 and all(
            [isinstance(page, Page) for page in pages])
        assert switcher_location in PageManager.SWITCHER_LOCATIONS.values()
        self._event_handler = event_handler
        self.pages = pages
        self.switcher_location = switcher_location
        self.switcher_pages = [(i, page) for i, page in enumerate(self.pages)]

        # Make sure all pages have an event_handler
        for page in pages:
            page.event_handler = self._event_handler

        # Create the switcher
        self.switcher_drawables = []
        if self.switcher_location != PageManager.SWITCHER_LOCATIONS["NONE"]:
            at_top = self.switcher_location == PageManager.SWITCHER_LOCATIONS[
                "TOP"]
            page_screen_size = (Constants.PI_TFT_SCREEN_SIZE[0],
                                Constants.PI_TFT_SCREEN_SIZE[1] -
                                PageManager.SWITCHER_HEIGHT)
            top = 0 if at_top else (Constants.PI_TFT_SCREEN_SIZE[1] -
                                    PageManager.SWITCHER_HEIGHT)
            width = Constants.PI_TFT_SCREEN_SIZE[0] / len(self.switcher_pages)
            for page_num, page in self.switcher_pages:
                page.screen_size = page_screen_size
                page.location_on_screen = (0, PageManager.SWITCHER_HEIGHT
                                           if at_top else 0)
                button = Drawables.Button(x=width * page_num,
                                          y=top,
                                          width=width,
                                          height=PageManager.SWITCHER_HEIGHT,
                                          text=page.page_name,
                                          font_size=15,
                                          bg_color=Colors.WHITE,
                                          fg_color=Colors.BLACK,
                                          callback=self._set_page_callback,
                                          args=[page_num])
                button.visible = True
                button.enable(self._event_handler)
                self.switcher_drawables.append(button)

        # Go to the starting page
        self.page_num = 0
        self.set_page(self.page_num)
Exemplo n.º 4
0
 def set_title(self,
               text,
               distance_from_top_of_graph=5,
               font_size=20,
               fg_color=None):
     """
     Set the title of the graph.
     :param text: The text to display
     :param distance_from_top_of_graph: Distance top of text is from the top of graph
     :param font_size: Font size
     :param fg_color: Font color
     :return: None
     """
     fg_color = self._plot["fg_color"] if fg_color is None else fg_color
     self._drawables["title"] = Drawables.Text(
         x=self.width / 2,
         y=self.y + distance_from_top_of_graph,
         text=text,
         font_size=font_size,
         fg_color=fg_color,
         align_x=Drawables.Text.ALIGN_X_CENTER,
         align_y=Drawables.Text.ALIGN_Y_TOP)
Exemplo n.º 5
0
 def set_x_label(self,
                 text,
                 distance_from_bottom_of_graph=5,
                 font_size=15,
                 fg_color=None):
     """
     Set the x label (this will be centered at the bottom of the chart)
     :param text: Text to display
     :param distance_from_bottom_of_graph: Distance bottom of text is from bottom of graph
     :param font_size: Font size
     :param fg_color: Font color
     :return: None
     """
     x = self.x + self._plot["offset_x"] + self._plot["width"] / 2
     y = self.y + self.height - distance_from_bottom_of_graph
     fg_color = self._plot["fg_color"] if fg_color is None else fg_color
     self._drawables["x_label"] = Drawables.Text(
         x=x,
         y=y,
         text=text,
         font_size=font_size,
         fg_color=fg_color,
         align_x=Drawables.Text.ALIGN_X_CENTER,
         align_y=Drawables.Text.ALIGN_Y_BOTTOM)
Exemplo n.º 6
0
    def set_bounds(self,
                   x_min=None,
                   x_max=None,
                   x_interval=None,
                   y_min=None,
                   y_max=None,
                   y_interval=None):
        """
        Set bounds for the two axes and the tick interval.  This does a lot of the calculations and creates the
        Drawables that are needed for the plot (axes, ticks, tick labels).  Call this method again when any of the
        bounds change.
        :param x_min: Minimum x value
        :param x_max: Maximum x value (must be greater than x_min)
        :param x_interval: Amount between tick marks on x axis (must be greater than 0)
        :param y_min: Minimum y value
        :param y_max: Maximum y value (must be greater than y_min)
        :param y_interval: Amount between tick marks on y axis (must be greater than 0)
        :return: None
        """
        if x_min is None: x_min = self._axis["x_min"]
        if x_max is None: x_max = self._axis["x_max"]
        if x_interval is None: x_interval = self._axis["x_interval"]
        if y_min is None: y_min = self._axis["y_min"]
        if y_max is None: y_max = self._axis["y_max"]
        if y_interval is None: y_interval = self._axis["y_interval"]

        # Make sure the inputs are reasonable
        assert x_max > x_min and x_interval > 0, (x_min, x_max, x_interval)
        assert y_max > y_min and y_interval > 0, (y_min, y_max, y_interval)

        # Store the variables
        self._axis["x_min"] = x_min
        self._axis["x_max"] = x_max
        self._axis["x_interval"] = x_interval
        self._axis["y_min"] = y_min
        self._axis["y_max"] = y_max
        self._axis["y_interval"] = y_interval

        # Some local variables
        plot_x = self.x + self._plot["offset_x"]
        plot_y = self.y + self._plot["offset_y"]
        width = self._plot["width"]
        height = self._plot["height"]

        # Reset the drawables
        self._drawables["x_ticks"] = []
        self._drawables["x_numbers"] = []
        self._drawables["y_ticks"] = []
        self._drawables["y_numbers"] = []

        # Figure out the axes
        self._axis_value_calculate()
        self._drawables["x_axis"] = Drawables.Line(plot_x,
                                                   self._axis["x_axis_y"],
                                                   width, 0,
                                                   self._plot["fg_color"])
        self._drawables["y_axis"] = Drawables.Line(self._axis["y_axis_x"],
                                                   plot_y, 0, height,
                                                   self._plot["fg_color"])

        self.update_distance_between_ticks()

        # Figure out x tick marks
        x_ticks_x, x_ticks_values = self.tick_marks(x_min, x_max, x_interval,
                                                    0)
        for tick_x, tick_value in zip(x_ticks_x, x_ticks_values):
            self._drawables["x_ticks"].append(
                Drawables.Line(tick_x, plot_y + height - 4, 0, 4,
                               self._plot["fg_color"]))
            self._drawables["x_numbers"].append(
                Drawables.Text(x=tick_x,
                               y=plot_y + height + 2,
                               text=str(tick_value),
                               font_size=12,
                               fg_color=self._plot["fg_color"],
                               align_x=Drawables.Text.ALIGN_X_CENTER,
                               align_y=Drawables.Text.ALIGN_Y_TOP))

        # Figure out y tick marks
        y_ticks_y, y_ticks_values = self.tick_marks(y_min, y_max, y_interval,
                                                    1)
        for tick_y, tick_value in zip(y_ticks_y, y_ticks_values):
            self._drawables["y_ticks"].append(
                Drawables.Line(plot_x, tick_y, 4, 0, self._plot["fg_color"]))
            self._drawables["y_numbers"].append(
                Drawables.Text(x=plot_x - 2,
                               y=tick_y,
                               text=str(tick_value),
                               font_size=12,
                               fg_color=self._plot["fg_color"],
                               align_x=Drawables.Text.ALIGN_X_RIGHT,
                               align_y=Drawables.Text.ALIGN_Y_CENTER))
Exemplo n.º 7
0
    def add_datum(self, values):
        """
        Add new datum.  This will automatically add the datum to the chart and draw a new row for this.  After the data
        point is added, the chart is resorted as desired (set the sorting scheme using add_sorting_scheme; default is
        FIFO so new data appears at the bottom).
        :param values: A dictionary of values (must have the same keys as the names of the columns and must have a
                    key/value pair for every column.
        :return: None
        """
        assert isinstance(values,
                          dict) and values.keys() == self.datasets.keys()

        # Mark that you can't add more datasets
        self._can_add_more_datasets = False

        # Extend old vertical lines
        for vertical in self._drawables["vertical"]:
            vertical.height += self._cell_heights

        # Add extra horizontal line
        horizontal_y = self.y + (max(
            [len(dataset["data"])
             for dataset in self.datasets.values()]) + 2) * self._cell_heights
        horizontal_width = sum(
            [dataset["cell_width"] for dataset in self.datasets.values()])
        self._drawables["horizontal"].append(
            Drawables.Line(self.x,
                           horizontal_y,
                           horizontal_width,
                           0,
                           color=self._fg_color))

        # Add text for the new row's data
        column_x = self.x
        for i, (dataset_name, value) in enumerate(values.items()):
            dataset = self.datasets[dataset_name]
            x_values = {
                Drawables.Text.ALIGN_X_LEFT:
                column_x + dataset["pad"],
                Drawables.Text.ALIGN_X_CENTER:
                column_x + dataset["cell_width"] / 2,
                Drawables.Text.ALIGN_X_RIGHT:
                column_x + dataset["cell_width"] - dataset["pad"]
            }
            y_value = self.y + (len(dataset["data"]) +
                                1.5) * self._cell_heights

            dataset["data"].append(value)
            dataset["insertion_order"].append(
                max(dataset["insertion_order"]) + 1)
            data_text = Drawables.Text(x_values[dataset["data_align_x"]],
                                       y_value,
                                       dataset["formatting"].format(value),
                                       dataset["data_font_size"],
                                       fg_color=dataset["font_color"],
                                       align_x=dataset["data_align_x"],
                                       align_y=Drawables.Text.ALIGN_Y_CENTER)
            self._drawables["data"][dataset_name].append(data_text)

            column_x += dataset["cell_width"]

        # Since new datapoint, sort if not FIFO
        if self._sorting_scheme != Sorting.FIFO:
            self._sort()
Exemplo n.º 8
0
    def add_dataset(self,
                    name,
                    data,
                    font_color=Colors.WHITE,
                    formatting="{}",
                    cell_width=100,
                    header_align_x=Drawables.Text.ALIGN_X_CENTER,
                    data_align_x=Drawables.Text.ALIGN_X_LEFT):
        """
        Add a new dataset (or column) to the chart.  Note that this funciton cannot be called after the add_datum
        function has been called.
        :param name: Name of the column (will show up as a header and must be unique)
        :param data: A list of data points for this column (all columns must have the same number of datapoints.
        :param font_color: Color of the font of the text in this column
        :param formatting: If you wat custom formatting; for example, if you want percent signs, you can pass in "{}%"
        :param cell_width: Width of the cells in this column
        :param header_align_x: How should the header be aligned (pick from Drawables.Text x align options)
        :param data_align_x: How should the data values be aligned (pick from Drawables.Text x align options)
        :return: None
        """
        assert isinstance(name, str) and name not in self.datasets
        assert isinstance(data, list)
        assert Colors.is_color(font_color)
        assert isinstance(formatting, str) and re.match(
            r"^[^{]*{[^{]*}[^{]*$", formatting)
        assert header_align_x in (Drawables.Text.ALIGN_X_LEFT,
                                  Drawables.Text.ALIGN_X_CENTER,
                                  Drawables.Text.ALIGN_X_RIGHT)
        assert data_align_x in (Drawables.Text.ALIGN_X_LEFT,
                                Drawables.Text.ALIGN_X_CENTER,
                                Drawables.Text.ALIGN_X_RIGHT)
        assert sum(
            [dataset["cell_width"]
             for dataset in self.datasets.values()]) + cell_width <= self.width
        assert all([
            len(data) == len(dataset["data"])
            for dataset in self.datasets.values()
        ])
        assert self._can_add_more_datasets

        # To pad left and right if alignments are selected to be to left and right
        pad = 4
        data_font_size = 12

        # Account for new vertical line
        vertical_line_height = (len(data) + 1) * self._cell_heights
        if len(self._drawables["vertical"]) == 0:
            self._drawables["vertical"].append(
                Drawables.Line(self.x,
                               self.y,
                               0,
                               vertical_line_height,
                               color=self._fg_color))
        column_x = self.x + sum(
            [dataset["cell_width"] for dataset in self.datasets.values()])
        self._drawables["vertical"].append(
            Drawables.Line(column_x + cell_width,
                           self.y,
                           0,
                           vertical_line_height,
                           color=self._fg_color))

        # Deal with all horizontal lines
        if len(self._drawables["horizontal"]) == 0:
            for i in range(len(data) + 2):
                horizontal = Drawables.Line(self.x,
                                            self.y + i * self._cell_heights,
                                            column_x + cell_width,
                                            0,
                                            color=self._fg_color)
                self._drawables["horizontal"].append(horizontal)
        else:
            for horizontal in self._drawables["horizontal"]:
                horizontal.width = column_x + cell_width

        # Deal with headers
        x_values = {
            Drawables.Text.ALIGN_X_LEFT: column_x + pad,
            Drawables.Text.ALIGN_X_CENTER: column_x + cell_width / 2,
            Drawables.Text.ALIGN_X_RIGHT: column_x + cell_width - pad
        }
        self._drawables["headers"].append(
            Drawables.Text(x_values[header_align_x],
                           self.y + self._cell_heights / 2,
                           name,
                           font_size=15,
                           fg_color=font_color,
                           align_x=header_align_x,
                           align_y=Drawables.Text.ALIGN_Y_CENTER))

        # Deal with data
        data_drawables = []
        for i, datum in enumerate(data):
            data_drawables.append(
                Drawables.Text(x_values[data_align_x],
                               self.y + (i + 1.5) * self._cell_heights,
                               formatting.format(datum),
                               font_size=data_font_size,
                               fg_color=font_color,
                               align_x=data_align_x,
                               align_y=Drawables.Text.ALIGN_Y_CENTER))
        self._drawables["data"][name] = data_drawables

        # Store the input values
        self.datasets[name] = {
            "data": data,
            "insertion_order": range(len(data)),
            "font_color": font_color,
            "formatting": formatting,
            "cell_width": cell_width,
            "data_font_size": data_font_size,
            "pad": pad,
            "header_align_x": header_align_x,
            "data_align_x": data_align_x
        }

        self._sort()