def draw_boxes(stdscr: window): """ This method draws the boxes on startup """ h = curses.LINES #Total height w = curses.COLS #Total width #Some debug values, remove these later text = "This is the start of a new window" # Clear screen stdscr.clear() stdscr.addstr(0, 0, 'This is the start of a new window') stdscr.noutrefresh() theight = 2 swidth = 15 mheight = h - theight - 2 mwidth = w - swidth - 2 win['t'] = curses.newwin(theight, mwidth, h - 1 - theight, 1) win['t'].addstr(0, 0, "This is the messages windows") win['m'] = curses.newwin(mheight, mwidth, 1, 1) win['m'].addstr(0, 0, "Type something here.") win['m'].timeout(0) win['s'] = curses.newwin(h - 2, swidth, 1, w - swidth - 1) win['s'].addstr(0, 0, "This is a side pane")
def on_wnd(self, wnd: _curses.window, theme, y, x, scroll, template, **kwargs): """ Render template on the window. TODO: Styles are a bit hacky. Args: y, x: Template start position scroll: skip this number of initial template lines (for scrolling) template: path to the template kwargs: template arguments. Returns: False: We hit the line limit during render (output cut) True: everything filled. """ splitter = re.compile('(<theme=[_a-zA-Z0-9]+>|</theme>)') theme_parser = re.compile('^<theme=([_a-zA-Z0-9]+)>$') lines, cols = wnd.getmaxyx() self.max_cols = cols # For wrap filter try: string = self.render_string(template, **kwargs) except jinja2.exceptions.TemplateError: log.exception(f"Template rendering {template} failed.") wnd.addstr(y, x, "*TEMPLATE RENDERING FAILED*") return True style = 0 for line in string.split("\n"): line = line.rstrip() chunks = re.split(splitter, line) col = x for chunk in chunks: match = re.match(theme_parser, chunk) if match: style_name = match.groups()[0] style = getattr(theme, style_name) continue if chunk == "</theme>": style = 0 continue chunk = jinja2.Markup(chunk).unescape() try: if scroll == 0: wnd.addnstr(y, col, chunk, cols - col, style) col += len(chunk) except _curses.error: # Overflow is ok at the LAST character in LAST line. # FIXME: Which makes it difficult to decide if we fit return False if scroll > 0: scroll -= 1 else: y += 1 if y == lines: return False return True
def add_title(self, text: str, win: _curses.window, align: str = "center") -> None: if align == "alignleft": cw = 2 elif align == "center": ch, cw, text = self.calculateCenter(text, win) elif align == "alignright": cw = win.getmaxyx()[1] - 2 - len(text) win.addstr(0, cw, f" {text.title()} ")
def redraw(self, wnd: _curses.window): "Refresh debug window" lines, cols = wnd.getmaxyx() wnd.erase() wnd.hline(0, 0, curses.ACS_HLINE, cols) self._logs = self._logs[-(lines-1):] line = 1 for log in self._logs: wnd.addstr(line, 0, log[:cols-1]) line += 1 wnd.refresh()
def redraw(self, wnd: _curses.window): "Refresh the view display" lines, cols = wnd.getmaxyx() wnd.erase() msg = "Incremental search: " + self.query wnd.addstr(0, 0, msg) cursor_position = len(msg) self._update_search_state() msg = "{}/{}".format(len(self.results), len(self.all_issues)) wnd.addstr(0, cols - len(msg), msg) if self.selected_idx >= len(self.results): self.selected_idx = max(0, len(self.results) - 1) line = 1 max_summary = cols - 10 - 5 for i, result in enumerate(self.results): if i == self.selected_idx: th_key = self.app.theme.ISSUE_KEY_SELECTED th_summary = self.app.theme.ISSUE_SUMMARY_SELECTED else: th_key = self.app.theme.ISSUE_KEY th_summary = self.app.theme.ISSUE_SUMMARY # TODO: Unified table generator j = result['fields'] summary = j["summary"] if len(summary) > max_summary: summary = summary[:max_summary] + "…" summary += " " * (cols - len(summary) - 16) msg = f"{result['key']:10s} {summary}" wnd.addstr(line, 0, "{:15}".format(result['key']), th_key) wnd.addstr(line, 15, summary[:cols - 15 - 1], th_summary) line += 1 if line == lines: break wnd.move(0, cursor_position)
def redraw(self, wnd: _curses.window): "Refresh the view display" lines, cols = wnd.getmaxyx() wnd.erase() line = 0 wnd.addstr(line, 0, f"View screen ({self.ticks} ticks):") line += 1 for i in range(0, curses.COLORS): wnd.addstr(line, i % cols, str(i % 10), curses.color_pair(i)) if (i+1) % cols == 0: line += 1 line += 1 for i, message in enumerate(self.messages): wnd.addstr(i + line, 0, "Msg: " + message) wnd.refresh()
def drawCrossword(self, win: _curses.window, board: Optional[List] = None): mh, mw = map(lambda x: x - 4, win.getmaxyx()) if not self.data: self.generateCrosswordBoard(mh, mw) self.data = None if self.data and (mh < self.data["height"] or mw < self.data["width"]): self.data = None if self.activeThread.get("gcb"): win.addstr(2, 2, f"generating Crossword {mh} x {mw}") win.refresh() elif self.data: ch, cw, board = self.calculateCenter( board or self.data["clueless"], win) for index, line in enumerate(board, start=ch): win.addstr(index, cw, line) for h, w, char in self.parseLoc.locaround: win.addstr(ch + h, cw + w, char, curses.color_pair(2))
def redraw(self, wnd: _curses.window): "Refresh the view display" wnd.clear() wnd.addstr(0, 0, "Dashboard", self.app.theme.TITLE) if self.update_in_progress: wnd.addstr(2, 0, "Updating database")
def redraw(self, wnd: _curses.window): "Refresh the view display" wnd.erase() wnd.addstr(0, 0, "Secondary view.")