Last active
June 4, 2023 22:10
-
-
Save nolageek/870d22914fe3ccb6d0bd3a400dde5e0d to your computer and use it in GitHub Desktop.
mystic scrolling list class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from mystic_bbs import * | |
x,y = termsize() | |
# ScrollingList is a class that provides functionality for displaying a list of items in a scrollable format. | |
# It supports various features like scrolling up and down, wrapping around the list, and selecting items. | |
# It also supports customization of the display format, including prefixes and suffixes for items, | |
# and separators for item attributes. | |
class ScrollingList: | |
# ListItem is a nested class that represents an item in the list. | |
# It supports arbitrary attributes through keyword arguments, | |
# and provides a method for displaying the item. | |
class ListItem: | |
def __init__(self, **kwargs): | |
self.attributes = kwargs | |
# Get an attribute with a default value if the attribute doesn't exist. | |
def get_attribute(self, attr_name, default=None): | |
return self.attributes.get(attr_name, default) | |
# Display the item with a given format. | |
def display(self, index, prefix, display_attributes, show_attribute_titles, attribute_separator, | |
item_suffix, selected_item_suffix, selected_item_prefix, index_separator,justify): | |
item_str = "{}{}{}".format(prefix, str(index+1).rjust(justify,'0'), index_separator) if 'index' in display_attributes else prefix | |
if not display_attributes: | |
display_attributes = ['index'] + list(self.attributes.keys()) | |
attributes = [] | |
for attr_name in display_attributes: | |
if attr_name in self.attributes: | |
if show_attribute_titles: | |
attributes.append("{}: {}".format(attr_name, self.attributes[attr_name])) | |
else: | |
attributes.append("{}".format(self.attributes[attr_name])) | |
item_str += attribute_separator.join(attributes) | |
item_str += selected_item_suffix if selected_item_prefix in prefix.strip() else item_suffix | |
writeln(item_str) | |
# Initialize the ScrollingList with a list of items and various default display options. | |
def __init__(self,items): | |
self.current_selection_global = 1 | |
self.current_selection = 1 | |
self.items = items | |
self.items_per_page = y/2 if len(self.items) > y/2 else len(self.items) / 2 | |
self.set_display_attributes('index', *list(self.items[0].attributes.keys())) | |
self.item_prefix = ' |07' | |
self.selected_item_prefix = '|23|00>' | |
self.attribute_separator = ', ' | |
self.item_suffix = '|$X79.|16|07' | |
self.selected_item_suffix = '|$X79 |16|07' | |
self.display_menu = True | |
self.show_attribute_titles = False | |
self.index_separator = ') ' | |
self.scrolling_wrap = False | |
self.item_x_prefix = None | |
self.item_y_prefix = None | |
# Set the attributes to be displayed for each item. | |
def set_display_attributes(self, *attributes): | |
self.display_attributes = list(attributes) | |
# Scroll up in the list. | |
def scroll_up(self): | |
if self.current_selection_global > 1: | |
self.current_selection_global -= 1 | |
if self.current_selection > 1: | |
self.current_selection -= 1 | |
elif self.scrolling_wrap: | |
self.current_selection_global = len(self.items) | |
self.current_selection = min(self.items_per_page, len(self.items)) | |
# Scroll down in the list. | |
def scroll_down(self): | |
if self.current_selection_global < len(self.items): | |
self.current_selection_global += 1 | |
if self.current_selection < self.items_per_page: | |
self.current_selection += 1 | |
elif self.scrolling_wrap: | |
self.current_selection_global = 1 | |
self.current_selection = 1 | |
# Display the current page of items in the list. | |
def display(self): | |
start_index = self.current_selection_global - self.current_selection | |
end_index = min(len(self.items), start_index + self.items_per_page) | |
displayed_items = self.items[start_index:end_index] | |
if self.display_menu: | |
for i, item in zip(range(start_index, end_index), displayed_items): | |
prefix = '' | |
if self.item_x_prefix is not None: # If item_x_prefix has been set | |
prefix += '|[X' + str(self.item_x_prefix).rjust(2,'0') + '|XX' | |
if self.item_y_prefix is not None: # If item_yx_prefix has been set | |
prefix += '|[Y' + str(self.item_y_prefix + (i - start_index)).rjust(2,'0') + '|XX' | |
prefix += self.selected_item_prefix if (i + 1) == self.current_selection_global else self.item_prefix | |
if isinstance(item, self.ListItem): | |
item.display(i, prefix, self.display_attributes, self.show_attribute_titles, | |
self.attribute_separator, self.item_suffix, self.selected_item_suffix, | |
self.selected_item_prefix, self.index_separator,int(len(str(len(self.items))))) | |
else: | |
item_str = "{}{}{} {}".format(prefix, (i+1).rjust(int(len(str(len(self.items)))),'0'), self.index_separator, item) | |
writeln(item_str) | |
for i in range(self.items_per_page - len(displayed_items)): | |
prefix = '' | |
if self.item_x_prefix is not None: # If item_x_prefix has been set | |
prefix += '|[X' + str(self.item_x_prefix).rjust(2,'0') + '|XX' | |
if self.item_y_prefix is not None: # If item_y_prefix has been set | |
prefix += '|[Y' + str(self.item_y_prefix + len(displayed_items) + i).rjust(2,'0') + '|XX' | |
prefix += self.item_prefix | |
writeln(prefix + self.item_suffix) | |
writeln('') # Add a new line | |
# get attribues of currently selected item | |
def get_selected_item(self): | |
if 0 < self.current_selection_global <= len(self.items): | |
return self.items[self.current_selection_global - 1] | |
return self.ListItem() # Return an empty ListItem if no item is selected | |
# Get number of currently selected item (out of total items) | |
def get_selected_index(self): | |
return self.current_selection_global | |
# Move forward or backward one page, go to first page, go to last page | |
def scroll_page(self, direction='next'): | |
# Scroll forward one page | |
if direction == 'next': | |
if self.current_selection_global + self.items_per_page <= len(self.items): | |
self.current_selection_global += self.items_per_page - self.current_selection + 1 | |
self.current_selection = 1 | |
elif self.scrolling_wrap and self.current_selection_global < len(self.items): | |
self.current_selection_global = len(self.items) | |
self.current_selection = min(self.items_per_page, len(self.items) % self.items_per_page or self.items_per_page) | |
elif self.scrolling_wrap: | |
self.current_selection_global = 1 | |
self.current_selection = 1 | |
# Scroll backward one page | |
elif direction == 'previous': | |
if self.current_selection_global - self.items_per_page > 1: | |
self.current_selection_global -= self.items_per_page | |
self.current_selection = 1 | |
elif self.scrolling_wrap and self.current_selection_global > 1: | |
self.current_selection_global = 1 | |
self.current_selection = 1 | |
elif self.scrolling_wrap: | |
self.current_selection_global = len(self.items) - (len(self.items) % self.items_per_page) + 1 | |
self.current_selection = 1 | |
else: | |
self.current_selection_global = 1 | |
self.current_selection = 1 | |
# Goto the first page | |
elif direction == 'first': | |
self.current_selection_global = 1 | |
self.current_selection = 1 | |
# Goto the last page | |
elif direction == 'last': | |
if len(self.items) % self.items_per_page == 0: | |
self.current_selection_global = len(self.items) - self.items_per_page + 1 | |
else: | |
self.current_selection_global = len(self.items) - (len(self.items) % self.items_per_page) + 1 | |
self.current_selection = min(self.items_per_page, len(self.items) - self.current_selection_global + 1) | |
self.current_selection_global += self.current_selection - 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment