Bladeren bron

Added static alert().

But I really need to clean up the boxes code.
Colors don't fit well into what I have, so I should
just pass in color strings for box and text.
Steve Thielemann 3 jaren geleden
bovenliggende
commit
df2474b598
3 gewijzigde bestanden met toevoegingen van 263 en 7 verwijderingen
  1. 16 3
      boxes.cpp
  2. 10 4
      boxes.h
  3. 237 0
      boxes.py

+ 16 - 3
boxes.cpp

@@ -72,7 +72,20 @@ std::string Boxes::bottom(void) {
   return line;
 }
 
-/*
+
 std::tuple<std::string, std::string, std::string>
-Boxes::alert(std::string message, int size, int color, int style = 1) {}
-*/
+Boxes::alert(std::string message, int color, int style, int size) {
+ size_t len = size;
+  if (len == 0) {
+    len = message.length();
+  } else {
+    while (message.length() < len)
+    message.append(" ");
+  }
+  Boxes abox(len, style, color);
+  std::string s1, s2, s3;
+  s1 = abox.top();
+  s2 = abox.row(message);
+  s3 = abox.bottom();
+  return std::make_tuple(s1, s2, s3);
+}

+ 10 - 4
boxes.h

@@ -14,6 +14,13 @@ enum {
 
 } BACK;
 
+/*
+
+I'm not sure if I want to try to store the color information in this or not.
+It might be easier to let this do boxes, and let something else do colors.
+
+ */
+
 class Boxes {
   struct box_style {
     const char *top_left;
@@ -47,10 +54,9 @@ public:
   std::string row(std::string &line);
   std::string bottom(void);
 
-  /*
-    std::tuple<std::string, std::string, std::string>
-    alert(std::string message, int size, int color, int style = 1);
-    */
+  static std::tuple<std::string, std::string, std::string>
+    alert(std::string message, int color, int style = 1, int size = 0);
+  
 };
 
 #endif

+ 237 - 0
boxes.py

@@ -0,0 +1,237 @@
+from colorama import Fore, Back, Style
+
+# see http://xahlee.info/comp/unicode_drawing_shapes.html
+
+
+def merge(color_string):
+    """ Given a string of colorama ANSI, merge them if you can. """
+    return color_string.replace("m\x1b[", ";")
+
+
+class Boxes(object):
+    """ Boxes makes nice ASCII graphic menus
+
+    Example:
+
+        c1 = merge(Style.BRIGHT + Fore.CYAN)
+        c2 = merge(Style.NORMAL + Fore.CYAN)
+
+        # Set the size of the box to 40  (Important!)
+        box = Boxes(40, color=c1)
+
+        self.queue_game.put(box.top())
+        # format string "{0:^40}".format("Text Centered")
+        # This centers the text into the size of the box.
+
+        self.queue_game.put(box.row(c1 + "{0:^40}".format("Scripts")))
+
+        # this draws the middle line.  (The line that goes across, but is
+        # connected on both sides to the one above it).
+        self.queue_game.put(box.middle())
+
+
+        def menu_item(ch, desc):
+            # Again we want the final string to be 40!
+            # c1 and c2 (below) take 0 space.
+            # We have " " + ch + " " + "-" + " " .. which equals 5
+            # So desc needs {:35} to pad out string out to 40 print chars.
+
+            row = " {0}{1} {2}-{3} {4:35}".format(c1, ch, c2, c1, desc)
+            # self.queue_game.put(
+            #     " " + c1 + ch + c2 + " - " + c1 + desc + self.nl
+            # )
+            self.queue_game.put(box.row(row))
+
+        menu_item("1", "Ports (Trades between two sectors)")
+        menu_item("2", "Explore (Strange new sectors)")
+        menu_item("3", "Space... the final frontier...")
+        menu_item("X", "eXit")
+        self.queue_game.put(box.bottom())
+
+    """
+
+    box_styles = (
+        # ┌──┐
+        # │  │
+        # ├──┤
+        # └──┘
+        {
+            "tl": "\xda",
+            "tr": "\xbf",
+            "top": "\xc4",
+            "side": "\xb3",
+            "bl": "\xc0",
+            "br": "\xd9",
+            "ml": "\xc3",
+            "mr": "\xb4",
+        },
+        # ╔══╗
+        # ║  ║
+        # ╠══╣
+        # ╚══╝
+        {
+            "tl": "\xc9",
+            "tr": "\xbb",
+            "top": "\xcd",
+            "side": "\xba",
+            "bl": "\xc8",
+            "br": "\xbc",
+            "ml": "\xcc",
+            "mr": "\xb9",
+        },
+        # ╒══╕
+        # │  │
+        # ╞══╡
+        # ╘══╛
+        {
+            "tl": "\xd5",
+            "tr": "\xb8",
+            "top": "\xcd",
+            "side": "\xb3",
+            "bl": "\xd4",
+            "br": "\xbe",
+            "ml": "\xc6",
+            "mr": "\xb5",
+        },
+        # ╓──╖
+        # ║  ║
+        # ╟──╢
+        # ╙──╜
+        {
+            "tl": "\xd6",
+            "tr": "\xb7",
+            "top": "\xc4",
+            "side": "\xba",
+            "bl": "\xd3",
+            "br": "\xbd",
+            "ml": "\xc7",
+            "mr": "\xb6",
+        },
+    )
+
+    def __init__(self, size: int, color="", style=1, start_nl=True):
+        """ Construct box
+
+        size is width of text inside the box.
+        (so actual width is size + 2).
+
+        color = Style of color to use.  
+        If color is blank, we don't use the RESET_ALL.
+
+        style=0  Is double lines.  
+        start_nl Should we start the top with a newline?
+        """
+        self.size = size
+        self.style = style
+        self.color = color
+        self.start_nl = start_nl
+
+        # default colors
+        # self.c = merge(Style.BRIGHT + Fore.WHITE + Back.BLUE)
+        # self.cp = merge(Style.BRIGHT + Fore.YELLOW + Back.BLUE)
+
+        # useful consts
+        self.r = Style.RESET_ALL
+        self.nl = "\n\r"
+        # self.bsb = "\b \b"
+
+    def top(self):
+        """ Output the TOP line. """
+        if self.color == "":
+            c = ""
+            r = ""
+        else:
+            c = self.color
+            r = self.r
+        s = self.box_styles[self.style]
+        if self.start_nl:
+            n = self.nl
+        else:
+            n = ""
+        return n + c + s["tl"] + s["top"] * self.size + s["tr"] + r + self.nl
+
+    def middle(self):
+        """ Output MIDDLE line.
+
+        This solid line goes completely across.
+        The edges connect to the top and bottom.
+        """
+        if self.color == "":
+            c = ""
+            r = ""
+        else:
+            c = self.color
+            r = self.r
+        s = self.box_styles[self.style]
+        return c + s["ml"] + s["top"] * self.size + s["mr"] + r + self.nl
+
+    def row(self, line):
+        """ Output content line.
+
+        NOTE:  the line length must match the box size.
+        Use "{0:30}".format(content) to match size of 30.
+        """
+        if self.color == "":
+            c = ""
+            r = ""
+        else:
+            c = self.color
+            r = self.r
+        s = self.box_styles[self.style]
+        return c + "{0}{1}{2}".format(s["side"], r + line + c, s["side"]) + r + self.nl
+
+    def bottom(self):
+        """ Output BOTTOM line. """
+        if self.color == "":
+            c = ""
+            r = ""
+        else:
+            c = self.color
+            r = self.r
+        s = self.box_styles[self.style]
+        return c + s["bl"] + s["top"] * self.size + s["br"] + r + self.nl
+
+    @staticmethod
+    def alert(message, length=0, pad=2, width=78, base="blue", style=1):
+        """
+        Display alert message
+
+        Example:
+        self.queue_game.put(Boxes.alert("Proxy done.", base="green"))
+
+        length: the printable character length.
+            If the string contains color codes, you'll need
+            to use this so it will be centered properly.
+            If not given, len(message) is used.
+        pad:  The spaces at the front and back of the message.
+        width:  Defaults to 78 chars wide.
+        base: The background color to use for the alert.
+        """
+        if base == "red":
+            color = merge(Style.BRIGHT + Fore.YELLOW + Back.RED)
+        elif base == "blue":
+            color = merge(Style.BRIGHT + Fore.YELLOW + Back.BLUE)
+        elif base == "green":
+            color = merge(Style.BRIGHT + Fore.YELLOW + Back.GREEN)
+        elif base == "cyan":
+            color = merge(Style.BRIGHT + Fore.YELLOW + Back.CYAN)
+        elif base == "magenta":
+            color = merge(Style.BRIGHT + Fore.YELLOW + Back.MAGENTA)
+        else:
+            # I don't know.
+            color = Style.RESET_ALL
+
+        if length == 0:
+            length = len(message)
+        box_size = length + pad * 2
+        boxpad = " " * pad
+        box = Boxes(box_size, color=color, style=style, start_nl=False)
+        msg = "{0}{1}{2}{3}".format(color, boxpad, message, boxpad)
+
+        # How much pad to add to the left side?
+        left_pad = (width - box_size + 2) // 2
+        pad = " " * left_pad
+        return "{0}{1}{2}{3}{4}{5}".format(
+            pad, box.top(), pad, box.row(msg), pad, box.bottom()
+        )
+