Title: Full-screen List Selection Dialog
Author: Ryan Kulla
Description: Displays a large number of clickable filenames in a full-screen dialog. Requires a list of filenames to be present in an external text file.
pygame version required: Any
Comments: file_master.py is full-screen dialog box that allows the user to select an item from a very large number of alternatives. Up to 165 items are shown per page, and the user can advance forward or backward through the list page by page. Selection is performed with the left mouse button. The instructions, though printed to the console instead of displayed on the screen, are simple and clear.
file_master has been abstracted from imgv, Mr. Kulla's image viewer program, and favors some of the features of that application. Alternatives are not generated at run time by globbing the contents of a directory - they are instead read from a static, pre-generated file listing like the one included in the downloadable archive. This works very well for a program like imgv, which uses "playlists" to organize images; it might work less well for a program needing a more conventional file-selection widget.
One way to improve file_master.py would be to allow the developer to specify callbacks that should be called when an item is selected, or the dialog is cancelled. Another area for possible improvement - change the item sorting function to properly sort names with a numeric component.
# list_master.py by Ryan Kulla (Sept. 2001) # Takes a python list with a virtually infinite amount of items (up to # 16 chars long). # If a list name is greater than 16 characters the rest of the chars will be # truncated and replaced with a tilde (~). # and prints them in a Pygame window 165 items at at time (in 640x480 # resolution. Spacebar to go to the next page, backspace to go to the # previous page. Left click an item to call a function on its name. import pygame, pygame.font from pygame.locals import * from string import replace import os.path def command_file_master(screen): font = pygame.font.Font(None, 15) (screen_pause, place, marker) = (0, 0, 0) x =  f = open("filelist") file_names = f.readlines() if len(file_names) == 0: return (file_names, x, 1, place, marker) f.close() file_names.sort() for count in range(len(file_names)): "get rid of any newlines in the list names" file_names[count] = replace(file_names[count], "\n", "") while 1: event = pygame.event.poll() if screen_pause == 1: while 1: event = pygame.event.wait() cursor = pygame.mouse.get_pos() if event.type == QUIT: raise SystemExit if event.type == MOUSEBUTTONDOWN and\ pygame.mouse.get_pressed(): for item in x: if item.collidepoint(cursor): print 'you clicked ', item if event.type == KEYDOWN and event.key == K_SPACE: print 'space bar hit' if not place >= len(file_names): screen_pause = 0 marker = 0 x =  break if event.type == KEYDOWN and event.key == K_BACKSPACE: print 'backspace hit' if ((place - marker) > 0): screen.fill(0) pygame.display.flip() screen_pause = 0 place -= (165 + marker) marker = 0 x =  break (file_names, x, screen_pause, place, marker) = file_master(screen,\ font, file_names, place, marker, x) pygame.time.delay(5) def file_master(screen, font, file_names, place, marker, x): screen.fill((0, 0, 0, 0)) pygame.display.update() font_height = font.size(file_names) screen_height = screen.get_height() max_file_width = 116 name_max = 16 # how many maximum characters a list name can be line = 65 # leave room at top of screen for other stuff col = 30 # where to start the first column count = 0 for name in file_names[place:]: count += 1 place += 1 marker += 1 if count >= 165 or place >= len(file_names): ren_name = os.path.basename(name) if len(ren_name) > name_max: ren_name = ren_name[:name_max] + '~' ren = font.render(ren_name, 1, (255, 255, 255), (0, 0, 0)) ren_rect = ren.get_rect() ren_rect = col ren_rect = line x.append((ren_rect, name)) screen.blit(ren, ren_rect) pygame.display.update(ren_rect) print 'space for next page, backspace for last page' return (file_names, x, 1, place, marker) ren_name = os.path.basename(name) if len(ren_name) > name_max: ren_name = ren_name[:name_max] + '~' ren = font.render(ren_name, 1, (255, 255, 255), (0, 0, 0)) ren_rect = ren.get_rect() ren_rect = col ren_rect = line x.append((ren_rect, name)) screen.blit(ren, ren_rect) line += 12 if (line + font_height) >= (screen_height - 15): line = 65 col += max_file_width pygame.display.update(ren_rect) return (file_names, x, 0, place, marker) def main(): pygame.init() screen = pygame.display.set_mode((640, 480)) print 'hit i to start' while 1: event = pygame.event.wait() if event.type == QUIT: break if event.type == KEYDOWN and event.key == K_i: command_file_master(screen) pygame.quit() if __name__=='__main__': main()