Title: Full-screen List Selection Dialog

Author: Ryan Kulla
Submission date: Sept. 4, 2001

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.

Download: list_master.zip, list_master.tar.gz

pygame version required: Any
SDL version required: Any
Python 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.

Messages: 0


# 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()[0]:
					for item in x:
						if item[0].collidepoint(cursor):
							print 'you clicked ', item[1]
				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[0])[1]
	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[0] = col
			ren_rect[1] = 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[0] = col
		ren_rect[1] = 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()

Main - Repository - Submit - News

Feedback