This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
mcedit/albow/file_dialogs.py

337 lines
9.3 KiB
Python

# -*- coding: utf-8 -*-
#
# Albow - File Dialogs
#
import os
from pygame import draw, Rect
from pygame.locals import *
from albow.widget import Widget
from albow.dialogs import Dialog, ask, alert
from albow.controls import Label, Button
from albow.fields import TextField
from albow.layout import Row, Column
from albow.palette_view import PaletteView
from albow.theme import ThemeProperty
class DirPathView(Widget):
def __init__(self, width, client, **kwds):
Widget.__init__(self, **kwds)
self.set_size_for_text(width)
self.client = client
def draw(self, surf):
frame = self.get_margin_rect()
image = self.font.render(self.client.directory, True, self.fg_color)
tw = image.get_width()
mw = frame.width
if tw <= mw:
x = 0
else:
x = mw - tw
surf.blit(image, (frame.left + x, frame.top))
class FileListView(PaletteView):
#scroll_button_color = (255, 255, 0)
def __init__(self, width, client, **kwds):
font = self.predict_font(kwds)
h = font.get_linesize()
d = 2 * self.predict(kwds, 'margin')
PaletteView.__init__(self, (width - d, h), 10, 1, scrolling=True, **kwds)
self.client = client
self.selection = None
self.names = []
def update(self):
client = self.client
dir = client.directory
suffixes = client.suffixes
def filter(name):
path = os.path.join(dir, name)
return os.path.isdir(path) or self.client.filter(path)
try:
names = [name for name in os.listdir(dir) if filter(name)]
#if not name.startswith(".") and filter(name)]
except EnvironmentError, e:
alert(u"%s: %s" % (dir, e))
names = []
self.names = sorted(names)
self.selection = None
self.scroll = 0
def num_items(self):
return len(self.names)
#def draw_prehighlight(self, surf, item_no, rect):
# draw.rect(surf, self.sel_color, rect)
def draw_item(self, surf, item_no, rect):
font = self.font
color = self.fg_color
buf = self.font.render(self.names[item_no], True, color)
surf.blit(buf, rect)
def click_item(self, item_no, e):
self.selection = item_no
self.client.dir_box_click(e.num_clicks == 2)
def item_is_selected(self, item_no):
return item_no == self.selection
def get_selected_name(self):
sel = self.selection
if sel is not None:
return self.names[sel]
else:
return ""
class FileDialog(Dialog):
box_width = 250
default_prompt = None
up_button_text = ThemeProperty("up_button_text")
def __init__(self, prompt=None, suffixes=None, **kwds):
Dialog.__init__(self, **kwds)
label = None
d = self.margin
self.suffixes = suffixes or ("",)
up_button = Button(self.up_button_text, action=self.go_up)
dir_box = DirPathView(self.box_width - up_button.width - 10, self)
self.dir_box = dir_box
top_row = Row([dir_box, up_button])
list_box = FileListView(self.box_width - 16, self)
self.list_box = list_box
ctrls = [top_row, list_box]
prompt = prompt or self.default_prompt
if prompt:
label = Label(prompt)
if self.saving:
filename_box = TextField(self.box_width)
filename_box.change_action = self.update
filename_box._enter_action = filename_box.enter_action
filename_box.enter_action = self.enter_action
self.filename_box = filename_box
ctrls.append(Column([label, filename_box], align='l', spacing=0))
else:
if label:
ctrls.insert(0, label)
ok_button = Button(self.ok_label, action=self.ok, enable=self.ok_enable)
self.ok_button = ok_button
cancel_button = Button("Cancel", action=self.cancel)
vbox = Column(ctrls, align='l', spacing=d)
vbox.topleft = (d, d)
y = vbox.bottom + d
ok_button.topleft = (vbox.left, y)
cancel_button.topright = (vbox.right, y)
self.add(vbox)
self.add(ok_button)
self.add(cancel_button)
self.shrink_wrap()
self._directory = None
self.directory = os.getcwdu()
#print "FileDialog: cwd =", repr(self.directory) ###
if self.saving:
filename_box.focus()
def get_directory(self):
return self._directory
def set_directory(self, x):
x = os.path.abspath(x)
while not os.path.exists(x):
y = os.path.dirname(x)
if y == x:
x = os.getcwdu()
break
x = y
if self._directory != x:
self._directory = x
self.list_box.update()
self.update()
directory = property(get_directory, set_directory)
def filter(self, path):
suffixes = self.suffixes
if not suffixes or os.path.isdir(path):
#return os.path.isfile(path)
return True
for suffix in suffixes:
if path.endswith(suffix.lower()):
return True
def update(self):
pass
def go_up(self):
self.directory = os.path.dirname(self.directory)
self.list_box.scroll_to_item(0)
def dir_box_click(self, double):
if double:
name = self.list_box.get_selected_name()
path = os.path.join(self.directory, name)
suffix = os.path.splitext(name)[1]
if suffix not in self.suffixes and os.path.isdir(path):
self.directory = path
else:
self.double_click_file(name)
self.update()
def enter_action(self):
self.filename_box._enter_action()
self.ok()
def ok(self):
self.dir_box_click(True)
#self.dismiss(True)
def cancel(self):
self.dismiss(False)
def key_down(self, evt):
k = evt.key
if k == K_RETURN or k == K_KP_ENTER:
self.dir_box_click(True)
if k == K_ESCAPE:
self.cancel()
class FileSaveDialog(FileDialog):
saving = True
default_prompt = "Save as:"
ok_label = "Save"
def get_filename(self):
return self.filename_box.value
def set_filename(self, x):
dsuf = self.suffixes[0]
if x.endswith(dsuf):
x = x[:-len(dsuf)]
self.filename_box.value = x
filename = property(get_filename, set_filename)
def get_pathname(self):
path = os.path.join(self.directory, self.filename_box.value)
suffixes = self.suffixes
if suffixes and not path.endswith(suffixes[0]):
path = path + suffixes[0]
return path
pathname = property(get_pathname)
def double_click_file(self, name):
self.filename_box.value = name
def ok(self):
path = self.pathname
if os.path.exists(path):
answer = ask("Replace existing '%s'?" % os.path.basename(path))
if answer != "OK":
return
#FileDialog.ok(self)
self.dismiss(True)
def update(self):
FileDialog.update(self)
def ok_enable(self):
return self.filename_box.text != ""
class FileOpenDialog(FileDialog):
saving = False
ok_label = "Open"
def get_pathname(self):
name = self.list_box.get_selected_name()
if name:
return os.path.join(self.directory, name)
else:
return None
pathname = property(get_pathname)
#def update(self):
# FileDialog.update(self)
def ok_enable(self):
path = self.pathname
enabled = self.item_is_choosable(path)
return enabled
def item_is_choosable(self, path):
return bool(path) and self.filter(path)
def double_click_file(self, name):
self.dismiss(True)
class LookForFileDialog(FileOpenDialog):
target = None
def __init__(self, target, **kwds):
FileOpenDialog.__init__(self, **kwds)
self.target = target
def item_is_choosable(self, path):
return path and os.path.basename(path) == self.target
def filter(self, name):
return name and os.path.basename(name) == self.target
def request_new_filename(prompt=None, suffix=None, extra_suffixes=None,
directory=None, filename=None, pathname=None):
if pathname:
directory, filename = os.path.split(pathname)
if extra_suffixes:
suffixes = extra_suffixes
else:
suffixes = []
if suffix:
suffixes = [suffix] + suffixes
dlog = FileSaveDialog(prompt=prompt, suffixes=suffixes)
if directory:
dlog.directory = directory
if filename:
dlog.filename = filename
if dlog.present():
return dlog.pathname
else:
return None
def request_old_filename(suffixes=None, directory=None):
dlog = FileOpenDialog(suffixes=suffixes)
if directory:
dlog.directory = directory
if dlog.present():
return dlog.pathname
else:
return None
def look_for_file_or_directory(target, prompt=None, directory=None):
dlog = LookForFileDialog(target=target, prompt=prompt)
if directory:
dlog.directory = directory
if dlog.present():
return dlog.pathname
else:
return None