diff options
author | Aleksey Lim <alsroot@member.fsf.org> | 2009-02-03 00:01:01 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@member.fsf.org> | 2009-02-03 00:01:01 (GMT) |
commit | a7dbc53a6657ad1e115f096e3072dc927847d853 (patch) | |
tree | 1ceea572568d9bd116f7ff4e142b9960861038d3 | |
parent | 6bf19eae5239760be2c11fc39b56e11cd40c3efc (diff) |
Mix in Char with OOP
-rw-r--r-- | char.py | 157 | ||||
-rw-r--r-- | document.py | 71 | ||||
-rw-r--r-- | ground.py | 13 | ||||
-rw-r--r-- | montage.py | 55 | ||||
-rw-r--r-- | sound.py | 4 | ||||
-rw-r--r-- | theme.py | 10 | ||||
-rw-r--r-- | utils.py | 19 |
7 files changed, 167 insertions, 162 deletions
@@ -18,96 +18,103 @@ import glob from gettext import gettext as _ import theme -from document import Document - -PREINSTALLED = 0 -CUSTOM = 1 +from utils import pixbuf, pixbuf2str def load(): + from document import Document + custom = THEMES[-1] + for i, f in enumerate( + [i for i in set(Document.tape) if not i.empty() and i.custom()]): + custom.frames[i] = f + +class Frame: + def __init__(self, image, type): + self._type = type + self._thumb = None + self._orig = None + self._filename = None + + if type == theme.RESTORED: + tmpfile = os.path.join(theme.SESSION_PATH, '.tmp.png') + file(tmpfile, 'w').write(image) + self._orig = theme.pixbuf(tmpfile) + os.unlink(tmpfile) + elif type == theme.CUSTOM: + self._thumb = theme.CUSTOM_FRAME_THUMB + elif type == theme.EMPTY: + self._type = theme.PREINSTALLED + self._thumb = theme.EMPTY_THUMB + self._orig = theme.EMPTY_ORIG + else: + self._filename = image + + def read(self): + if not self._orig: + return '' + else: + return pixbuf2str(self._orig) + + def empty(self): + return self._thumb == theme.EMPTY_THUMB - index = 0 - loaded = {} - for i in range(theme.TAPE_COUNT): - orig = Document.tape[i].orig - if Document.tape[i].filename or loaded.has_key(orig): - continue - loaded[orig] = True - custom._origs[index] = orig - custom._thumbs[index] = theme.scale(orig) - index += 1 + def custom(self): + return self._type != theme.PREINSTALLED + + def thumb(self): + if self._thumb == None: + self._thumb = theme.scale(self.orig()) + return self._thumb + + def orig(self): + if self._orig == None: + if self._type != theme.PREINSTALLED: + return theme.EMPTY_ORIG + self._orig = theme.pixbuf(self._filename) + return self._orig + + def select(self): + if self._type != theme.CUSTOM or self._orig: + return True; + self._orig = theme.choose(lambda t, file: theme.pixbuf(file)) + self._thumb = theme.scale(self.orig()) + return self._orig != None + + def filename(self): + return self._filename class Char: - def __init__(self, name, file, dir, type): + def __init__(self, name, thumbfile, dir): self.name = name - self._thumb = theme.pixbuf(file, theme.THUMB_SIZE) - self._type = type - self._thumbs = {} - self._origs = {} - self._filenames = [] + self.frames = [] - if type != CUSTOM: + if dir: for i in sorted(glob.glob(theme.path(dir, '*'))): - self._filenames.append(os.path.join(dir, os.path.basename(i))) - - def filename(self, index): - if self._type == CUSTOM: - return None - elif index >= len(self._filenames): - return theme.EMPTY_FILENAME + self.frames.append(Frame( + os.path.join(dir, os.path.basename(i)), + theme.PREINSTALLED)) + for i in range(len(self.frames)-1, + theme.FRAME_ROWS*theme.FRAME_COLS): + self.frames.append(Frame(None, theme.EMPTY)) + self._thumb = theme.pixbuf(thumbfile, theme.THUMB_SIZE) else: - return self._filenames[index] - - def thumb(self, index = None): - if index == None: - return self._thumb - - pix = self._thumbs.get(index) - - if pix == None: - if self._type == CUSTOM: - pix = self._thumb - else: - if index < len(self._filenames): - pix = theme.pixbuf(self._filenames[index], theme.THUMB_SIZE) - else: - pix = theme.EMPTY_THUMB - self._thumbs[index] = pix - - return pix - - def orig(self, index): - pix = self._origs.get(index) - - if pix == None: - if self._type == CUSTOM: - pix = theme.choose(lambda t, file: theme.pixbuf(file)) - if pix: - self._thumbs[index] = theme.scale(pix) - self._origs[index] = pix - else: - if index < len(self._filenames): - pix = theme.pixbuf(self._filenames[index]) - self._origs[index] = pix - else: - pix = theme.EMPTY_ORIG - - return pix + for i in range(0, theme.FRAME_ROWS*theme.FRAME_COLS): + self.frames.append(Frame(None, theme.CUSTOM)) + self._thumb = theme.CUSTOM_FRAME_THUMB + + def thumb(self): + return self._thumb def clean(self, index): - if self._type != CUSTOM: - return - if self._thumbs.has_key(index): - del self._thumbs[index] - if self._origs.has_key(index): - del self._origs[index] + if self.frames[index].custom(): + self.frames[index] = Frame(None, theme.CUSTOM) THEMES = ( Char(_('Elephant'), 'images/pics/Elephant/bigelephant0.gif', - 'images/pics/Elephant', PREINSTALLED), + 'images/pics/Elephant'), Char(_('Space Blob'), 'images/pics/SpaceBlob/bigblob8.gif', - 'images/pics/SpaceBlob', PREINSTALLED), + 'images/pics/SpaceBlob'), Char(_('Turkey'), 'images/pics/Turkey/bigturkey1.gif', - 'images/pics/Turkey', PREINSTALLED), + 'images/pics/Turkey'), None, - Char(_('Custom'), 'images/pics/custom.png', None, CUSTOM)) + Char(_('Custom'), None, None)) diff --git a/document.py b/document.py index 72e571e..d9227fa 100644 --- a/document.py +++ b/document.py @@ -14,6 +14,7 @@ import os import gtk +from zipfile import ZipFile from xml.etree.ElementTree import Element, SubElement, tostring, fromstring import theme @@ -21,24 +22,23 @@ from sound import Sound from ground import Ground from utils import * +from char import Frame + class Document: tape = [] ground = None sound = None - class Tape: - def __init__(self): - self.clean() - - def clean(self): - self.orig = theme.EMPTY_ORIG - self.filename = theme.EMPTY_FILENAME for i in range(theme.TAPE_COUNT): - tape.append(Tape()) + tape.append(Frame(None, theme.EMPTY)) + +def clean(index): + from char import Frame + Document.tape[index] = Frame(None, theme.EMPTY) def save(filepath): - zip = Zip(filepath, 'w') + zip = ZipFile(filepath, 'w') manifest = Element('memorize') def _save(node, arcname, value): @@ -54,20 +54,24 @@ def save(filepath): _save(SubElement(manifest, 'ground'), 'ground.png', Document.ground) _save(SubElement(manifest, 'sound'), 'sound', Document.sound) - saved = {} + arcfiles = {} + for i, frame in enumerate( + [i for i in set(Document.tape) if not i.empty() and i.custom()]): + arcfiles[frame] = 'frame%03d.png' % i + zip.writestr(arcfiles[frame], frame.read()) + tape = SubElement(manifest, 'tape') - for i in range(theme.TAPE_COUNT): - frame = SubElement(tape, 'frame') - if Document.tape[i].filename: - frame.attrib['preinstalled'] = '1' - frame.attrib['filename'] = Document.tape[i].filename + for i, frame in enumerate(Document.tape): + if frame.empty(): + continue + node = SubElement(tape, 'frame') + if frame.custom(): + node.attrib['custom'] = '1' + node.attrib['filename'] = arcfiles[frame] else: - frame.attrib['preinstalled'] = '0' - arcname = saved.get(Document.tape[i].orig) - if not arcname: - arcname = saved[Document.tape[i].orig] = 'frame%03d.png' % i - zip.write_pixbuf(arcname, Document.tape[i].orig) - frame.attrib['filename'] = arcname + node.attrib['custom'] = '0' + node.attrib['filename'] = frame.filename() + node.attrib['index'] = str(i) zip.writestr('MANIFEST.xml', tostring(manifest, encoding='utf-8')) zip.close() @@ -76,7 +80,7 @@ def save(filepath): shutil.copy(filepath, '/tmp/foo.zip') def load(filepath): - zip = Zip(filepath, 'r') + zip = ZipFile(filepath, 'r') manifest = fromstring(zip.read('MANIFEST.xml')) def _load(node, klass): @@ -91,21 +95,18 @@ def load(filepath): Document.sound = _load(manifest.find('sound'), Sound) loaded = {} - for i, frame in enumerate(manifest.findall('tape/frame')): + for node in manifest.findall('tape/frame'): + i = int(node.attrib['index']) if i >= theme.TAPE_COUNT: continue - if int(frame.attrib['preinstalled']): - if frame.attrib['filename'] == theme.EMPTY_FILENAME: - Document.tape[i].orig = theme.EMPTY_ORIG - else: - Document.tape[i].orig = theme.pixbuf(frame.attrib['filename']) - Document.tape[i].filename = frame.attrib['filename'] + filename = node.attrib['filename'] + if int(node.attrib['custom']): + frame = loaded.get(filename) + if not frame: + frame = loaded[filename] = Frame( + zip.read(filename), theme.RESTORED) + Document.tape[i] = frame else: - pixbuf = loaded.get(frame.attrib['filename']) - if not pixbuf: - pixbuf = zip.read_pixbuf(frame.attrib['filename']) - loaded[frame.attrib['filename']] = pixbuf - Document.tape[i].orig = pixbuf - Document.tape[i].filename = None + Document.tape[i] = Frame(filename, theme.PREINSTALLED) zip.close() @@ -14,12 +14,12 @@ import os import gtk -import cStringIO from gettext import gettext as _ from sugar.graphics.objectchooser import ObjectChooser import theme +from utils import pixbuf, pixbuf2str def load(): from document import Document @@ -36,7 +36,7 @@ class Ground: if type == theme.RESTORED: tmpfile = os.path.join(theme.SESSION_PATH, '.tmp.png') file(tmpfile, 'w').write(image) - self._orig = gtk.gdk.pixbuf_new_from_file(tmpfile) + self._orig = theme.pixbuf(tmpfile) os.unlink(tmpfile) self._filename = 'ground.png' else: @@ -47,12 +47,7 @@ class Ground: return self._type != theme.PREINSTALLED def read(self): - def push(data, buffer): - buffer.write(data) - - buffer = cStringIO.StringIO() - self._orig.save_to_callback(push, 'png', user_data=buffer) - return buffer.getvalue() + pixbuf2str(self._orig) def filename(self): return self._filename @@ -65,7 +60,7 @@ class Ground: def orig(self): return self._orig - def change(self): + def select(self): if self._type != theme.CUSTOM: return self return theme.choose( @@ -25,7 +25,7 @@ import theme import char import ground import sound -from document import Document +from document import Document, clean from utils import * def play(): @@ -36,31 +36,31 @@ def stop(): View.playing = None def set_tempo(tempo): - View.delay = 10 + (10-tempo) * 100 + View.delay = 10 + (10-int(tempo)) * 100 if View.playing: gobject.source_remove(View.playing) View.playing = gobject.timeout_add(View.delay, _play_tape) def clear_tape(): for i in range(TAPE_COUNT): - Document.tape[i].clean() + clean(i) View.tape[i].child.set_from_pixbuf(theme.EMPTY_THUMB) - View.screen.fgpixbuf = Document.tape[View.tape_selected].orig + View.screen.fgpixbuf = Document.tape[View.tape_selected].orig() View.screen.draw() def _play_tape(): if not View.playing: return False - View.screen.fgpixbuf = Document.tape[View.play_tape_num].orig + View.screen.fgpixbuf = Document.tape[View.play_tape_num].orig() View.screen.draw() for i in range(theme.TAPE_COUNT): View.play_tape_num += 1 if View.play_tape_num == TAPE_COUNT: View.play_tape_num = 0 - if Document.tape[View.play_tape_num].orig == theme.EMPTY_ORIG: + if Document.tape[View.play_tape_num].empty(): continue return True @@ -118,14 +118,10 @@ class View(gtk.EventBox): # frames table - from math import ceil + self.table = gtk.Table(theme.FRAME_ROWS, columns=theme.FRAME_COLS, + homogeneous=False) - rows = max((DESKTOP_HEIGHT - THUMB_SIZE*3) / THUMB_SIZE, - int(ceil(float(FRAME_COUNT) / FRAME_COLS))) - - self.table = gtk.Table(rows, columns=theme.FRAME_COLS, homogeneous=False) - - for y in range(rows): + for y in range(theme.FRAME_ROWS): for x in range(theme.FRAME_COLS): image = gtk.Image() self._frames.append(image) @@ -297,14 +293,14 @@ class View(gtk.EventBox): Document.sound, self._sound_cb), False, False) for i in range(theme.TAPE_COUNT): - View.tape[i].child.set_from_pixbuf(theme.scale(Document.tape[i].orig)) + View.tape[i].child.set_from_pixbuf(Document.tape[i].thumb()) self._tape_cb(None, None, 0) return False def _tape_cb(self, widget, event, index): if event and event.button == 3: - Document.tape[index].clean() + clean(index) View.tape[index].child.set_from_pixbuf(theme.EMPTY_THUMB) tape = View.tape[index] @@ -320,32 +316,29 @@ class View(gtk.EventBox): gtk.gdk.color_parse(BLACK)) View.tape_selected = index - self.screen.fgpixbuf = Document.tape[index].orig + self.screen.fgpixbuf = Document.tape[index].orig() self.screen.draw() - def _frame_cb(self, widget, event, frame): + def _frame_cb(self, widget, event, i): + if event.button == 3: - self.char.clean(frame) - self._frames[frame].set_from_pixbuf(self.char.thumb(frame)) + self.char.clean(i) + self._frames[i].set_from_pixbuf(self.char.frames[i].thumb()) else: - orig = self.char.orig(frame) - if not orig: return - thumb = self.char.thumb(frame) - - Document.tape[View.tape_selected].orig = orig - Document.tape[View.tape_selected].filename = self.char.filename(frame) - - View.tape[View.tape_selected].child.set_from_pixbuf(thumb) - self._frames[frame].set_from_pixbuf(thumb) - self._tape_cb(None, None, View.tape_selected) + frame = self.char.frames[i] + if frame.select(): + Document.tape[View.tape_selected] = frame + View.tape[View.tape_selected].child.set_from_pixbuf(frame.thumb()) + self._frames[i].set_from_pixbuf(frame.thumb()) + self._tape_cb(None, None, View.tape_selected) def _char_cb(self, widget, closure): self.char = widget.props.value for i in range(len(self._frames)): - self._frames[i].set_from_pixbuf(self.char.thumb(i)) + self._frames[i].set_from_pixbuf(self.char.frames[i].thumb()) def _combo_cb(self, widget, cb): - choice = widget.props.value.change() + choice = widget.props.value.select() if not choice: widget.set_active(self._prev_combo_selected[widget]) @@ -71,7 +71,7 @@ class Sound: def thumb(self): return self._thumb - def change(self): + def select(self): out = self if self._type == theme.CUSTOM: @@ -104,7 +104,7 @@ Sound.current = THEMES[0] def play(): Sound.playing = True - Sound.current.change() + Sound.current.select() def stop(): Sound.playing = False @@ -15,6 +15,7 @@ import os import gtk import shutil +from math import ceil from sugar.activity.activity import get_bundle_path, get_activity_root from sugar.graphics import style @@ -23,6 +24,7 @@ PREINSTALLED = 0 CUSTOM = 1 JOURNAL = 2 RESTORED = 3 +EMPTY = 4 SOUND_SPEAKER = 'images/sounds/speaker.png' SOUND_MUTE = 'images/sounds/custom.png' @@ -41,6 +43,9 @@ FRAME_COLS = max(1, ((DESKTOP_WIDTH-LOGO_WIDTH) - min(DESKTOP_HEIGHT-THUMB_SIZE-THUMB_SIZE/2, DESKTOP_WIDTH-LOGO_WIDTH)) / THUMB_SIZE) +FRAME_ROWS = max((DESKTOP_HEIGHT - THUMB_SIZE*3) / THUMB_SIZE, + int(ceil(float(FRAME_COUNT) / FRAME_COLS))) + BORDER_WIDTH = 10 # Colors from the Rich's UI design @@ -102,6 +107,11 @@ EMPTY_FILENAME = 'images/pics/empty.png' EMPTY_ORIG = pixbuf(EMPTY_FILENAME) EMPTY_THUMB = scale(EMPTY_ORIG) +#CUSTOM_GROUND EMPTY_FILENAME = 'images/pics/empty.png' + +CUSTOM_FRAME_ORIG = pixbuf('images/pics/custom.png') +CUSTOM_FRAME_THUMB = scale(CUSTOM_FRAME_ORIG) + def choose(out_fun): from sugar.graphics.objectchooser import ObjectChooser @@ -15,7 +15,6 @@ import os import gtk import pango -import zipfile import cStringIO import sugar @@ -24,17 +23,16 @@ from sugar.graphics.icon import Icon from theme import * -class Zip(zipfile.ZipFile): - def __init__(self, *args): - zipfile.ZipFile.__init__(self, *args) +def pixbuf2str(pixbuf): + def push(data, buffer): + buffer.write(data) + + buffer = cStringIO.StringIO() + pixbuf.save_to_callback(push, 'png', user_data=buffer) + return buffer.getvalue() + - def write_pixbuf(self, arcfile, pixbuf): - def push(data, buffer): - buffer.write(data) - buffer = cStringIO.StringIO() - pixbuf.save_to_callback(push, 'png', user_data=buffer) - self.writestr(arcfile, buffer.getvalue()) def read_pixbuf(self, arcfile): tmpfile = os.path.join(SESSION_PATH, 'tmp.png') @@ -43,6 +41,7 @@ class Zip(zipfile.ZipFile): os.unlink(tmpfile) return out + class ComboBox(sugar.graphics.combobox.ComboBox): def __init__(self): sugar.graphics.combobox.ComboBox.__init__(self) |