diff options
65 files changed, 566 insertions, 114 deletions
@@ -1,6 +1,62 @@ SliderPuzzleActivity.py SliderPuzzleUI.py SliderPuzzleWidget.py -images/image_XO.svg -images/image_XO2.svg -images/image_XO3.svg
\ No newline at end of file +utils.py +icons/circle-x.svg +icons/circle-check.svg +images/default_thumb.svg +images/XO's/image_XO.svg +images/XO's/image_XO2.svg +images/XO's/image_XO3.svg +images/XO's/thumb.svg +images/jumbler starter pics/image_2kgl_h250_w250_lg.gif +images/jumbler starter pics/image_aisc_h250_w313_lg.gif +images/jumbler starter pics/image_atih_h250_w250_lg.gif +images/jumbler starter pics/image_atlo_h250_w333_lg.gif +images/jumbler starter pics/image_bbhs_h250_w250_lg.gif +images/jumbler starter pics/image_bbof_h250_w250_lg.gif +images/jumbler starter pics/image_bgim_h250_w250_lg.gif +images/jumbler starter pics/image_bmar_h250_w230_lg.gif +images/jumbler starter pics/image_btfi_h250_w331_lg.gif +images/jumbler starter pics/image_cal_h250_w165_lg.gif +images/jumbler starter pics/image_chmk_h250_w250_lg.gif +images/jumbler starter pics/image_clor_h250_w250_lg.gif +images/jumbler starter pics/image_col_h250_w333_lg.gif +images/jumbler starter pics/image_czvb_h250_w250_lg.gif +images/jumbler starter pics/image_dan_h250_w424_lg.gif +images/jumbler starter pics/image_devin_music_w333_lg.gif +images/jumbler starter pics/image_djstf_h250_w411_lg.gif +images/jumbler starter pics/image_drti_h250_w322_lg.gif +images/jumbler starter pics/image_esim_h250_w250_lg.gif +images/jumbler starter pics/image_evms_h250_w320_lg.gif +images/jumbler starter pics/image_fsuw_h250_w250_lg.gif +images/jumbler starter pics/image_higc_h250_w250_lg.gif +images/jumbler starter pics/image_howl_h250_w250_lg.gif +images/jumbler starter pics/image_hsnr_h250_w421_lg.gif +images/jumbler starter pics/image_joc_h250_w333_lg.gif +images/jumbler starter pics/image_jppr_h250_w403_lg.gif +images/jumbler starter pics/image_justi_h250_w333_lg.gif +images/jumbler starter pics/image_kili_h250_w387_lg.gif +images/jumbler starter pics/image_kitty_lg.gif +images/jumbler starter pics/image_lehf_h250_w250_lg.gif +images/jumbler starter pics/image_mbmg_h250_w250_lg.gif +images/jumbler starter pics/image_mdic_h250_w250_lg.gif +images/jumbler starter pics/image_mdwl_h250_w250_lg.gif +images/jumbler starter pics/image_mrfg_h250_w333_lg.gif +images/jumbler starter pics/image_nimo_h250_w299_lg.gif +images/jumbler starter pics/image_oitn_h250_w250_lg.gif +images/jumbler starter pics/image_s1macaw_lg.gif +images/jumbler starter pics/image_sdkc_h250_w250_lg.gif +images/jumbler starter pics/image_skat_h250_w363_lg.gif +images/jumbler starter pics/image_skst_h250_w253_lg.gif +images/jumbler starter pics/image_slls_h250_w333_lg.gif +images/jumbler starter pics/image_smrr_h250_w371_lg.gif +images/jumbler starter pics/image_sxykitton_lg.gif +images/jumbler starter pics/image_tbtn_h250_w365_lg.gif +images/jumbler starter pics/image_tral_h250_w404_lg.gif +images/jumbler starter pics/image_tsoc_h250_w421_lg.gif +images/jumbler starter pics/image_weird_h250_w384_lg.gif +images/jumbler starter pics/image_wpwa_h250_w250_lg.gif +images/jumbler starter pics/image_xxmrtwigxx_lg.gif +images/jumbler starter pics/thumb.gif +locale/pt/LC_MESSAGES/pt.po diff --git a/SliderPuzzleUI.py b/SliderPuzzleUI.py index be0865b..4dfa55e 100644 --- a/SliderPuzzleUI.py +++ b/SliderPuzzleUI.py @@ -27,9 +27,11 @@ import pygtk pygtk.require('2.0') import gtk, gobject, pango +from utils import load_image + from gettext import gettext as _ from glob import glob -from SliderPuzzleWidget import SliderPuzzleWidget, calculate_relative_size +from SliderPuzzleWidget import SliderPuzzleWidget from time import time import os @@ -44,7 +46,7 @@ BORDER_ALL = BORDER_VERTICAL | BORDER_HORIZONTAL class BorderFrame (gtk.EventBox): def __init__ (self, border=BORDER_ALL, size=5, color="#0000FF"): gtk.EventBox.__init__(self) - self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) + self.set_border_color(gtk.gdk.color_parse(color)) self.inner = gtk.EventBox() align = gtk.Alignment(1.0,1.0,1.0,1.0) padding = [0,0,0,0] @@ -58,35 +60,68 @@ class BorderFrame (gtk.EventBox): padding[3] = size align.set_padding(*padding) align.add(self.inner) - #self.inner = align gtk.EventBox.add(self, align) + self.stack = [] + + def set_border_color (self, color): + gtk.EventBox.modify_bg(self, gtk.STATE_NORMAL, color) + + def modify_bg (self, state, color): + self.inner.modify_bg(state, color) def add (self, widget): + self.stack.append(widget) self.inner.add(widget) - def do_size_request (self, requisition): - print requisition.width, requisition.height, self.inner.child - gtk.EventBox.do_size_request(self, requisition) - self.inner.child.request_resize() + def push (self, widget): + widget.set_size_request(*self.inner.child.get_size_request()) + self.inner.remove(self.inner.child) + self.add(widget) + + def pop (self): + if len(self.stack) > 1: + self.inner.remove(self.inner.child) + del self.stack[-1] + self.inner.add(self.stack[-1]) + + def get_allocation (self): + return self.inner.get_allocation() class TimerWidget (gtk.HBox): def __init__ (self): gtk.HBox.__init__(self) - self.pack_start(gtk.Label(), True, True, 0) - eb = gtk.EventBox() - eb.add(gtk.Label(_("Time: "))) - self.pack_start(eb, False) - eb = gtk.EventBox() + spacer = gtk.Label() + spacer.set_size_request(20, -1) + self.counter = BorderFrame(size=1, color="#4444FF") + self.counter.set_size_request(100, -1) + self.counter.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#DD4040")) + hb = gtk.HBox() + self.counter.add(hb) + self.pack_start(spacer, False) + self.pack_start(gtk.Label(_("Time: ")), False) + + #eb = gtk.EventBox() + self.prepare_icons() + self.icon = gtk.Image() + self.icon.set_from_pixbuf(self.icons[1]) + hb.pack_start(self.icon, False, False, 5) self.time_label = gtk.Label("--:--") - eb.add(self.time_label) - self.pack_start(eb, False) - self.pack_end(gtk.Label(), True, True, 0) + hb.pack_end(self.time_label, False, False, 5) + self.pack_start(self.counter, False) self.connect("button-press-event", self.process_click) self.start_time = None self.timer_id = None self.finished = False + def prepare_icons (self): + self.icons = [] + self.icons.append(load_image("icons/circle-x.svg")) + self.icons.append(load_image("icons/circle-check.svg")) + + def modify_bg(self, state, color): + self.foreach(lambda x: x is not self.counter and x.modify_bg(state, color)) + def reset (self): self.finished = False if self.timer_id is not None: @@ -99,6 +134,7 @@ class TimerWidget (gtk.HBox): def start (self): if self.finished: return + self.icon.set_from_pixbuf(self.icons[0]) if self.start_time is None: self.start_time = time() else: @@ -108,6 +144,7 @@ class TimerWidget (gtk.HBox): self.timer_id = gobject.timeout_add(1000, self.do_tick) def stop (self, finished=False): + self.icon.set_from_pixbuf(self.icons[1]) if self.timer_id is not None: gobject.source_remove(self.timer_id) self.timer_id = None @@ -125,7 +162,7 @@ class TimerWidget (gtk.HBox): def do_tick (self): t = time() - self.start_time - self.time_label.set_text("%0.2i:%0.2i" % (t/60, t%60)) + self.time_label.set_text("%i:%0.2i" % (t/60, t%60)) return True class ImageSelectorWidget (gtk.Table): @@ -149,8 +186,12 @@ class ImageSelectorWidget (gtk.Table): self.attach(br, 2,3,1,2) self.attach(gtk.Label(),3,4,1,2) self.filename = None + self.show_all() + self.image.set_size_request(width, height) def next (self, *args, **kwargs): + if not len(self.images): + return if self.filename is None or self.filename not in self.images: pos = -1 else: @@ -161,6 +202,8 @@ class ImageSelectorWidget (gtk.Table): self.load_image(self.images[pos]) def previous (self, *args, **kwargs): + if not len(self.images): + return if self.filename is None or self.filename not in self.images: pos = len(self.images) else: @@ -172,36 +215,87 @@ class ImageSelectorWidget (gtk.Table): def set_image_dir (self, directory): self.images = glob(os.path.join(directory, "image_*")) - self.load_image(self.images[0]) + if len(self.images): + self.load_image(self.images[0]) +# else: +# self.load_image("activity/activity-sliderpuzzle.svg") def load_image(self, filename): """ Loads an image from the file """ - img = gtk.Image() - img.set_from_file(filename) - pb = img.get_pixbuf() - w,h = calculate_relative_size(pb.get_width(), pb.get_height(), self.width, self.height) - scaled_pb = pb.scale_simple(w,h, gtk.gdk.INTERP_BILINEAR) - self.image.set_from_pixbuf(scaled_pb) - self.filename = filename + self.image.set_from_pixbuf(load_image(filename, self.width, self.height)) + if len(self.images): + self.filename = filename + +class CategorySelector (gtk.ScrolledWindow): + __gsignals__ = {'selected' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,))} + + def __init__ (self, path, title=None): + gtk.ScrolledWindow.__init__ (self) + self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + + self.path = path + self.thumbs = [] + model = self.get_model(path) + + treeview = gtk.TreeView() + col = gtk.TreeViewColumn(title) + r1 = gtk.CellRendererPixbuf() + r2 = gtk.CellRendererText() + col.pack_start(r1, False) + col.pack_start(r2, True) + col.set_cell_data_func(r1, self.cell_pb) + col.set_attributes(r2, text=1) + treeview.append_column(col) + treeview.set_model(model) + + treeview.connect("cursor-changed", self.do_select) + self.add(treeview) + self.show_all() + + def cell_pb (self, tvcolumn, cell, model, it): + cell.set_property('pixbuf', self.thumbs[model.get_value(it, 2)]) + + def get_pb (self, path): + thumbs = glob(os.path.join(path, "thumb.*")) + thumbs.extend(glob(os.path.join(self.path, "default_thumb.*"))) + thumbs = filter(lambda x: os.path.exists(x), thumbs) + thumbs.append(None) + return load_image(thumbs[0], 32,32) + + def get_model (self, path): + # Each row is (path/dirname, pretty name, 0 based index) + store = gtk.ListStore(str, str, int) + files = [os.path.join(path, x) for x in os.listdir(path) if not x.startswith('.')] + i = 0 + for fullpath, prettyname in [(x, _(os.path.basename(x))) for x in files if os.path.isdir(x)]: + store.append([fullpath, prettyname, len(self.thumbs)]) + self.thumbs.append(self.get_pb(fullpath)) + return store + + def do_select (self, tree, *args, **kwargs): + tv, it = tree.get_selection().get_selected() + self.emit("selected", tv.get_value(it,0)) class SliderPuzzleUI: def __init__(self, parent): # Basic window settings self.window = parent - settings = self.window.get_settings() - settings.set_string_property("gtk-font-name", "sans bold 10", "SliderPuzzleUI") - self.window.set_title("Slider Puzzle Activity") + #settings = self.window.get_settings() + #settings.set_string_property("gtk-font-name", "sans bold 10", "SliderPuzzleUI") + self.window.set_title(_("Slider Puzzle Activity")) + + bgcolor = gtk.gdk.color_parse("#DDDD40") # The actual game widget - self.game = SliderPuzzleWidget() + self.game = SliderPuzzleWidget(9, 480, 480) self.game.connect("solved", self.do_solve) - self.game.load_image("images/image_XO.svg", 480, 480) + self.window.connect("key_press_event",self.game.process_key) # The image selector with thumbnail - self.thumb = ImageSelectorWidget(200) + self.thumb = ImageSelectorWidget(200, 200) self.thumb.set_image_dir("images") + self.thumb.connect("button_press_event", self.do_select_category) #self.thumb.load_image("images/image_XO.svg") - self.window.connect("key_press_event",self.game.process_key, None) # Buttons for selecting the number of pieces cutter = gtk.VBox() @@ -223,8 +317,10 @@ class SliderPuzzleUI: # The bottom left buttons buttons_box = BorderFrame(BORDER_TOP) + buttons_box.modify_bg(gtk.STATE_NORMAL, bgcolor) inner_buttons_box = gtk.VBox(False, 5) - btn_add = gtk.Button(_("Add My Own Picture")) + inner_buttons_box.set_border_width(10) + btn_add = gtk.Button(_("My Own Picture")) inner_buttons_box.add(btn_add) btn_solve = gtk.Button(_("Solve")) btn_solve.connect("clicked", self.do_solve) @@ -236,19 +332,23 @@ class SliderPuzzleUI: # The timer widget self.timer = TimerWidget() + self.timer.modify_bg(gtk.STATE_NORMAL, bgcolor) + self.timer.set_border_width(3) # Everything on the left side of the game widget goes here + event_controls_box = gtk.EventBox() + event_controls_box.modify_bg(gtk.STATE_NORMAL, bgcolor) controls_box = gtk.VBox(False, 5) - controls_box.add(self.timer) + controls_box.pack_start(self.timer, False, False) controls_box.add(thumb_box) controls_box.add(buttons_box) - + event_controls_box.add(controls_box) # This is the horizontal container that holds everything wrapping_box = gtk.HBox() - wrapping_box.add(controls_box) - game_box = BorderFrame(BORDER_LEFT) - game_box.add(self.game) - wrapping_box.add(game_box) + wrapping_box.add(event_controls_box) + self.game_box = BorderFrame(BORDER_LEFT) + self.game_box.add(self.game) + wrapping_box.add(self.game_box) # Put a border around the whole thing inner = BorderFrame() inner.add(wrapping_box) @@ -262,31 +362,48 @@ class SliderPuzzleUI: try: # This fails if testing outside Sugar self.window.set_canvas(outter) - self.dcntr = 0 - self.window.connect("activated", do_check_resize) - self.window.connect("deactivated", do_check_resize) except: self.window.add(outter) - + self.window.show_all() - self.timer.start() + self.do_select_category(self) + #self.timer.start() def set_nr_pieces (self, btn, nr_pieces): - self.game.load_image(self.thumb.filename) - self.game.set_nr_pieces(nr_pieces) - self.timer.reset() - - def do_jumble (self, btn): - self.game.randomize() - self.timer.reset() + if self.thumb.filename: + if not self.game.get_parent(): + self.game_box.pop() + self.game.load_image(self.thumb.filename) + self.game.set_nr_pieces(nr_pieces) + self.timer.reset() + + def do_jumble (self, *args, **kwargs): + if self.thumb.filename: + if not self.game.get_parent(): + self.game_box.pop() + self.game.load_image(self.thumb.filename) + self.game.randomize() + self.timer.reset() def do_solve (self, btn): - self.game.show_image() - self.timer.stop(True) - - def do_check_resize (self, *args, **kwargs): - self.dbg_label.set_text("%i" % self.dcntr) - self.dcntr += 1 + if self.thumb.filename: + if not self.game.get_parent(): + self.game_box.pop() + self.game.show_image() + self.timer.stop(True) + + def do_select_category(self, owner, *args, **kwargs): + if isinstance(owner, CategorySelector): + self.thumb.set_image_dir(args[0]) + self.game_box.pop() + else: + if self.game.get_parent(): + s = CategorySelector("images", _("Select Image Category")) + s.connect("selected", self.do_select_category) + s.show() + self.game_box.push(s) + else: + self.game_box.pop() def main(): win = gtk.Window(gtk.WINDOW_TOPLEVEL) diff --git a/SliderPuzzleWidget.py b/SliderPuzzleWidget.py index 1d08f30..17b5c6b 100644 --- a/SliderPuzzleWidget.py +++ b/SliderPuzzleWidget.py @@ -29,11 +29,11 @@ import pygtk pygtk.require('2.0') import gtk, gobject -from math import sqrt, pow, ceil +from utils import load_image, calculate_matrix, debug + from types import TupleType, ListType from random import random from time import time -import sys ### # General Information @@ -49,47 +49,6 @@ SLIDE_DOWN = 2 SLIDE_LEFT = 3 SLIDE_RIGHT = 4 -DEBUG = True - -def debug (what): - if DEBUG: - print >> sys.stderr, what - -def calculate_matrix (pieces): - """ Given a number of pieces, calculate the best fit 2 dimensional matrix """ - rows = int(sqrt(pieces)) - cols = int(float(pieces) / rows) - return rows*cols, rows, cols - -def calculate_relative_size (orig_width, orig_height, width, height): - """ If any of width or height is -1, the returned width or height will be in the same relative scale as the - given part. - >>> calculate_relative_size(100, 100, 50, -1) - (50, 50) - >>> calculate_relative_size(200, 100, -1, 50) - (100, 50) - - If both width and height are given, the same values will be returned. If none is given, the orig_* will be returned. - >>> calculate_relative_size(200,200,100,150) - (100, 150) - >>> calculate_relative_size(200,200,-1,-1) - (200, 200) - """ - if width < 0: - if height >= 0: - out_w = int(orig_width * (float(height)/orig_height)) - out_h = height - else: - out_w = orig_width - out_h = orig_height - else: - out_w = width - if height < 0: - out_h = int(orig_height * (float(width)/orig_width)) - else: - out_h = height - return out_w, out_h - ### # Game Logic ### @@ -363,13 +322,15 @@ class SliderPuzzleMap (object): class SliderPuzzleWidget (gtk.Table): __gsignals__ = {'solved' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())} - def __init__ (self, pieces=9): + def __init__ (self, pieces=9, width=480, height=480): self.jumbler = SliderPuzzleMap(pieces, self.jumblermap_piece_move_cb) # We take this from the jumbler object because it may have altered our requested value self.nr_pieces = self.jumbler.pieces gtk.Table.__init__(self, self.jumbler.rowsize, self.jumbler.colsize) self.image = gtk.Image() - self.randomize() + self.width = width + self.height = height + self.set_size_request(width, height) def prepare_pieces (self): """ set up a list of UI objects that will serve as pieces, ordered correctly """ @@ -411,7 +372,7 @@ class SliderPuzzleWidget (gtk.Table): # i is the 1 based index of the piece self.jumbler.do_move_piece(i) - def process_key (self, w, e, o): + def process_key (self, w, e): k = gtk.gdk.keyval_name(e.keyval) if k in up_key: self.jumbler.do_move(SLIDE_UP) @@ -450,17 +411,20 @@ class SliderPuzzleWidget (gtk.Table): self.jumbler.randomize() self.full_refresh() - def load_image (self, filename, width=-1, height=-1): - """ Loads an image from the file """ + def load_image (self, filename, width=0, height=0): + """ Loads an image from the file. + width and height are processed as follows: + -1 : follow the loaded image size + 0 : follow the size set on widget instantiation + * : use that specific size""" + if width == 0: + width = self.width + if height == 0: + height = self.height if width == height == -1: self.image.set_from_file(filename) else: - img = gtk.Image() - img.set_from_file(filename) - pb = img.get_pixbuf() - w,h = calculate_relative_size(pb.get_width(), pb.get_height(), width, height) - scaled_pb = pb.scale_simple(w,h, gtk.gdk.INTERP_BILINEAR) - self.image.set_from_pixbuf(scaled_pb) + self.image.set_from_pixbuf(load_image(filename, width, height)) self.full_refresh() def show_image (self): diff --git a/activity/activity.info b/activity/activity.info index a696bc1..53d4c92 100644 --- a/activity/activity.info +++ b/activity/activity.info @@ -1,5 +1,5 @@ [Activity] -name = SliderPuzzle +name = Slider Puzzle service_name = org.worldwideworkshop.olpc.SliderPuzzle class = SliderPuzzleActivity.SliderPuzzleActivity icon = activity-sliderpuzzle diff --git a/icons/circle-check.svg b/icons/circle-check.svg new file mode 100644 index 0000000..2c14ef1 --- /dev/null +++ b/icons/circle-check.svg @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + id="Icon" + width="19.997831" + height="19.999567" + viewBox="0 0 46.115 46.121" + overflow="visible" + enable-background="new 0 0 46.115 46.121" + xml:space="preserve" + sodipodi:version="0.32" + inkscape:version="0.45" + sodipodi:docname="circle-check.svg" + sodipodi:docbase="/home/cn/work/clients/wwworkshop/pygtk/SliderPuzzle.activity/icons" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + sodipodi:modified="true"><metadata + id="metadata8260"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs + id="defs8258" /><sodipodi:namedview + inkscape:window-height="621" + inkscape:window-width="872" + inkscape:pageshadow="2" + inkscape:pageopacity="1" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#5affff" + id="base" + inkscape:zoom="8.8246138" + inkscape:cx="23.057501" + inkscape:cy="23.060499" + inkscape:window-x="79" + inkscape:window-y="202" + inkscape:current-layer="Icon" + width="20px" + height="20px" /> +<path + d="M 23.056,1.75 C 34.826,1.75 44.363,11.293 44.363,23.058 C 44.363,34.826 34.826,44.37 23.056,44.37 C 11.286,44.37 1.747,34.826 1.747,23.058 C 1.748,11.293 11.287,1.75 23.056,1.75 z " + id="path8251" + style="fill:none;stroke:#ffffff;stroke-width:3.5" /> +<line + x1="12.000999" + y1="24.509001" + x2="19.605999" + y2="32.112999" + id="line8253" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round" /> +<line + x1="19.588999" + y1="32.155998" + x2="34.802002" + y2="16.941" + id="line8255" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round" /> +</svg>
\ No newline at end of file diff --git a/icons/circle-x.svg b/icons/circle-x.svg new file mode 100644 index 0000000..a7333c9 --- /dev/null +++ b/icons/circle-x.svg @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + id="Icon" + width="19.997644" + height="19.997644" + viewBox="0 0 46.119 46.121" + overflow="visible" + enable-background="new 0 0 46.119 46.121" + xml:space="preserve" + sodipodi:version="0.32" + inkscape:version="0.45" + sodipodi:docname="circle-x.svg" + sodipodi:docbase="/home/cn/work/clients/wwworkshop/pygtk/SliderPuzzle.activity/icons" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + sodipodi:modified="true"><metadata + id="metadata3355"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs + id="defs3353" /><sodipodi:namedview + inkscape:window-height="621" + inkscape:window-width="872" + inkscape:pageshadow="2" + inkscape:pageopacity="1" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#0dffff" + id="base" + inkscape:zoom="8.8246138" + inkscape:cx="23.0595" + inkscape:cy="23.060499" + inkscape:window-x="20" + inkscape:window-y="134" + inkscape:current-layer="Icon" + width="20px" + height="20px" /> +<circle + cx="23.059999" + cy="23.061001" + r="21.311001" + id="circle3346" + sodipodi:cx="23.059999" + sodipodi:cy="23.061001" + sodipodi:rx="21.311001" + sodipodi:ry="21.311001" + transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-9.5556897,23.057075)" + style="fill:#ff0000;fill-opacity:0;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1" /> +<line + x1="30.564133" + y1="30.765953" + x2="15.350733" + y2="15.552551" + id="line3348" + style="fill:#aaaaaa;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-opacity:1" /> +<line + x1="15.352855" + y1="30.764538" + x2="30.564133" + y2="15.551845" + id="line3350" + style="fill:#aaaaaa;fill-opacity:0;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-opacity:1" /> +</svg>
\ No newline at end of file diff --git a/images/image_XO.svg b/images/XO's/image_XO.svg index 6e4a7b3..6e4a7b3 100644 --- a/images/image_XO.svg +++ b/images/XO's/image_XO.svg diff --git a/images/image_XO2.svg b/images/XO's/image_XO2.svg index fdc6618..fdc6618 100644 --- a/images/image_XO2.svg +++ b/images/XO's/image_XO2.svg diff --git a/images/image_XO3.svg b/images/XO's/image_XO3.svg index 590b077..590b077 100644 --- a/images/image_XO3.svg +++ b/images/XO's/image_XO3.svg diff --git a/images/image_XO2.svg b/images/XO's/thumb.svg index fdc6618..fdc6618 100644 --- a/images/image_XO2.svg +++ b/images/XO's/thumb.svg diff --git a/images/image_XO.svg b/images/default_thumb.svg index 6e4a7b3..6e4a7b3 100644 --- a/images/image_XO.svg +++ b/images/default_thumb.svg diff --git a/images/jumbler starter pics/image_2kgl_h250_w250_lg.gif b/images/jumbler starter pics/image_2kgl_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..f6c720f --- /dev/null +++ b/images/jumbler starter pics/image_2kgl_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_aisc_h250_w313_lg.gif b/images/jumbler starter pics/image_aisc_h250_w313_lg.gif Binary files differnew file mode 100644 index 0000000..177b1cb --- /dev/null +++ b/images/jumbler starter pics/image_aisc_h250_w313_lg.gif diff --git a/images/jumbler starter pics/image_atih_h250_w250_lg.gif b/images/jumbler starter pics/image_atih_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..5979e64 --- /dev/null +++ b/images/jumbler starter pics/image_atih_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_atlo_h250_w333_lg.gif b/images/jumbler starter pics/image_atlo_h250_w333_lg.gif Binary files differnew file mode 100644 index 0000000..12e473e --- /dev/null +++ b/images/jumbler starter pics/image_atlo_h250_w333_lg.gif diff --git a/images/jumbler starter pics/image_bbhs_h250_w250_lg.gif b/images/jumbler starter pics/image_bbhs_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..9077ac2 --- /dev/null +++ b/images/jumbler starter pics/image_bbhs_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_bbof_h250_w250_lg.gif b/images/jumbler starter pics/image_bbof_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..eb14e49 --- /dev/null +++ b/images/jumbler starter pics/image_bbof_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_bgim_h250_w250_lg.gif b/images/jumbler starter pics/image_bgim_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..f10dca1 --- /dev/null +++ b/images/jumbler starter pics/image_bgim_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_bmar_h250_w230_lg.gif b/images/jumbler starter pics/image_bmar_h250_w230_lg.gif Binary files differnew file mode 100644 index 0000000..51f2c8f --- /dev/null +++ b/images/jumbler starter pics/image_bmar_h250_w230_lg.gif diff --git a/images/jumbler starter pics/image_btfi_h250_w331_lg.gif b/images/jumbler starter pics/image_btfi_h250_w331_lg.gif Binary files differnew file mode 100644 index 0000000..b0f05e3 --- /dev/null +++ b/images/jumbler starter pics/image_btfi_h250_w331_lg.gif diff --git a/images/jumbler starter pics/image_cal_h250_w165_lg.gif b/images/jumbler starter pics/image_cal_h250_w165_lg.gif Binary files differnew file mode 100644 index 0000000..d020ed7 --- /dev/null +++ b/images/jumbler starter pics/image_cal_h250_w165_lg.gif diff --git a/images/jumbler starter pics/image_chmk_h250_w250_lg.gif b/images/jumbler starter pics/image_chmk_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..a0f650e --- /dev/null +++ b/images/jumbler starter pics/image_chmk_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_clor_h250_w250_lg.gif b/images/jumbler starter pics/image_clor_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..5f3e045 --- /dev/null +++ b/images/jumbler starter pics/image_clor_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_col_h250_w333_lg.gif b/images/jumbler starter pics/image_col_h250_w333_lg.gif Binary files differnew file mode 100644 index 0000000..c2dc2a8 --- /dev/null +++ b/images/jumbler starter pics/image_col_h250_w333_lg.gif diff --git a/images/jumbler starter pics/image_czvb_h250_w250_lg.gif b/images/jumbler starter pics/image_czvb_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..6517bd6 --- /dev/null +++ b/images/jumbler starter pics/image_czvb_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_dan_h250_w424_lg.gif b/images/jumbler starter pics/image_dan_h250_w424_lg.gif Binary files differnew file mode 100644 index 0000000..f2fc0fd --- /dev/null +++ b/images/jumbler starter pics/image_dan_h250_w424_lg.gif diff --git a/images/jumbler starter pics/image_devin_music_w333_lg.gif b/images/jumbler starter pics/image_devin_music_w333_lg.gif Binary files differnew file mode 100644 index 0000000..c185ac4 --- /dev/null +++ b/images/jumbler starter pics/image_devin_music_w333_lg.gif diff --git a/images/jumbler starter pics/image_djstf_h250_w411_lg.gif b/images/jumbler starter pics/image_djstf_h250_w411_lg.gif Binary files differnew file mode 100644 index 0000000..e7eff4f --- /dev/null +++ b/images/jumbler starter pics/image_djstf_h250_w411_lg.gif diff --git a/images/jumbler starter pics/image_drti_h250_w322_lg.gif b/images/jumbler starter pics/image_drti_h250_w322_lg.gif Binary files differnew file mode 100644 index 0000000..bd14a1d --- /dev/null +++ b/images/jumbler starter pics/image_drti_h250_w322_lg.gif diff --git a/images/jumbler starter pics/image_esim_h250_w250_lg.gif b/images/jumbler starter pics/image_esim_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..807df48 --- /dev/null +++ b/images/jumbler starter pics/image_esim_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_evms_h250_w320_lg.gif b/images/jumbler starter pics/image_evms_h250_w320_lg.gif Binary files differnew file mode 100644 index 0000000..3b2c45e --- /dev/null +++ b/images/jumbler starter pics/image_evms_h250_w320_lg.gif diff --git a/images/jumbler starter pics/image_fsuw_h250_w250_lg.gif b/images/jumbler starter pics/image_fsuw_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..69eb3cf --- /dev/null +++ b/images/jumbler starter pics/image_fsuw_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_higc_h250_w250_lg.gif b/images/jumbler starter pics/image_higc_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..f52c054 --- /dev/null +++ b/images/jumbler starter pics/image_higc_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_howl_h250_w250_lg.gif b/images/jumbler starter pics/image_howl_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..ce77aa4 --- /dev/null +++ b/images/jumbler starter pics/image_howl_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_hsnr_h250_w421_lg.gif b/images/jumbler starter pics/image_hsnr_h250_w421_lg.gif Binary files differnew file mode 100644 index 0000000..566cf2d --- /dev/null +++ b/images/jumbler starter pics/image_hsnr_h250_w421_lg.gif diff --git a/images/jumbler starter pics/image_joc_h250_w333_lg.gif b/images/jumbler starter pics/image_joc_h250_w333_lg.gif Binary files differnew file mode 100644 index 0000000..89da89a --- /dev/null +++ b/images/jumbler starter pics/image_joc_h250_w333_lg.gif diff --git a/images/jumbler starter pics/image_jppr_h250_w403_lg.gif b/images/jumbler starter pics/image_jppr_h250_w403_lg.gif Binary files differnew file mode 100644 index 0000000..4069ada --- /dev/null +++ b/images/jumbler starter pics/image_jppr_h250_w403_lg.gif diff --git a/images/jumbler starter pics/image_justi_h250_w333_lg.gif b/images/jumbler starter pics/image_justi_h250_w333_lg.gif Binary files differnew file mode 100644 index 0000000..1adccf2 --- /dev/null +++ b/images/jumbler starter pics/image_justi_h250_w333_lg.gif diff --git a/images/jumbler starter pics/image_kili_h250_w387_lg.gif b/images/jumbler starter pics/image_kili_h250_w387_lg.gif Binary files differnew file mode 100644 index 0000000..a61eaf0 --- /dev/null +++ b/images/jumbler starter pics/image_kili_h250_w387_lg.gif diff --git a/images/jumbler starter pics/image_kitty_lg.gif b/images/jumbler starter pics/image_kitty_lg.gif Binary files differnew file mode 100644 index 0000000..c197337 --- /dev/null +++ b/images/jumbler starter pics/image_kitty_lg.gif diff --git a/images/jumbler starter pics/image_lehf_h250_w250_lg.gif b/images/jumbler starter pics/image_lehf_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..16c25bf --- /dev/null +++ b/images/jumbler starter pics/image_lehf_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_mbmg_h250_w250_lg.gif b/images/jumbler starter pics/image_mbmg_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..3250b7e --- /dev/null +++ b/images/jumbler starter pics/image_mbmg_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_mdic_h250_w250_lg.gif b/images/jumbler starter pics/image_mdic_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..365b0dd --- /dev/null +++ b/images/jumbler starter pics/image_mdic_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_mdwl_h250_w250_lg.gif b/images/jumbler starter pics/image_mdwl_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..5979d62 --- /dev/null +++ b/images/jumbler starter pics/image_mdwl_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_mrfg_h250_w333_lg.gif b/images/jumbler starter pics/image_mrfg_h250_w333_lg.gif Binary files differnew file mode 100644 index 0000000..4d8ecd4 --- /dev/null +++ b/images/jumbler starter pics/image_mrfg_h250_w333_lg.gif diff --git a/images/jumbler starter pics/image_nimo_h250_w299_lg.gif b/images/jumbler starter pics/image_nimo_h250_w299_lg.gif Binary files differnew file mode 100644 index 0000000..f87bc58 --- /dev/null +++ b/images/jumbler starter pics/image_nimo_h250_w299_lg.gif diff --git a/images/jumbler starter pics/image_oitn_h250_w250_lg.gif b/images/jumbler starter pics/image_oitn_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..3b0f64a --- /dev/null +++ b/images/jumbler starter pics/image_oitn_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_s1macaw_lg.gif b/images/jumbler starter pics/image_s1macaw_lg.gif Binary files differnew file mode 100644 index 0000000..6138e2c --- /dev/null +++ b/images/jumbler starter pics/image_s1macaw_lg.gif diff --git a/images/jumbler starter pics/image_sdkc_h250_w250_lg.gif b/images/jumbler starter pics/image_sdkc_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..3f08736 --- /dev/null +++ b/images/jumbler starter pics/image_sdkc_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_skat_h250_w363_lg.gif b/images/jumbler starter pics/image_skat_h250_w363_lg.gif Binary files differnew file mode 100644 index 0000000..1c2a875 --- /dev/null +++ b/images/jumbler starter pics/image_skat_h250_w363_lg.gif diff --git a/images/jumbler starter pics/image_skst_h250_w253_lg.gif b/images/jumbler starter pics/image_skst_h250_w253_lg.gif Binary files differnew file mode 100644 index 0000000..d16102a --- /dev/null +++ b/images/jumbler starter pics/image_skst_h250_w253_lg.gif diff --git a/images/jumbler starter pics/image_slls_h250_w333_lg.gif b/images/jumbler starter pics/image_slls_h250_w333_lg.gif Binary files differnew file mode 100644 index 0000000..54cc3bb --- /dev/null +++ b/images/jumbler starter pics/image_slls_h250_w333_lg.gif diff --git a/images/jumbler starter pics/image_smrr_h250_w371_lg.gif b/images/jumbler starter pics/image_smrr_h250_w371_lg.gif Binary files differnew file mode 100644 index 0000000..202eb9d --- /dev/null +++ b/images/jumbler starter pics/image_smrr_h250_w371_lg.gif diff --git a/images/jumbler starter pics/image_sxykitton_lg.gif b/images/jumbler starter pics/image_sxykitton_lg.gif Binary files differnew file mode 100644 index 0000000..08a1597 --- /dev/null +++ b/images/jumbler starter pics/image_sxykitton_lg.gif diff --git a/images/jumbler starter pics/image_tbtn_h250_w365_lg.gif b/images/jumbler starter pics/image_tbtn_h250_w365_lg.gif Binary files differnew file mode 100644 index 0000000..05b22e3 --- /dev/null +++ b/images/jumbler starter pics/image_tbtn_h250_w365_lg.gif diff --git a/images/jumbler starter pics/image_tral_h250_w404_lg.gif b/images/jumbler starter pics/image_tral_h250_w404_lg.gif Binary files differnew file mode 100644 index 0000000..c70ce73 --- /dev/null +++ b/images/jumbler starter pics/image_tral_h250_w404_lg.gif diff --git a/images/jumbler starter pics/image_tsoc_h250_w421_lg.gif b/images/jumbler starter pics/image_tsoc_h250_w421_lg.gif Binary files differnew file mode 100644 index 0000000..96a337a --- /dev/null +++ b/images/jumbler starter pics/image_tsoc_h250_w421_lg.gif diff --git a/images/jumbler starter pics/image_weird_h250_w384_lg.gif b/images/jumbler starter pics/image_weird_h250_w384_lg.gif Binary files differnew file mode 100644 index 0000000..0f603bf --- /dev/null +++ b/images/jumbler starter pics/image_weird_h250_w384_lg.gif diff --git a/images/jumbler starter pics/image_wpwa_h250_w250_lg.gif b/images/jumbler starter pics/image_wpwa_h250_w250_lg.gif Binary files differnew file mode 100644 index 0000000..c7739de --- /dev/null +++ b/images/jumbler starter pics/image_wpwa_h250_w250_lg.gif diff --git a/images/jumbler starter pics/image_xxmrtwigxx_lg.gif b/images/jumbler starter pics/image_xxmrtwigxx_lg.gif Binary files differnew file mode 100644 index 0000000..4f8a273 --- /dev/null +++ b/images/jumbler starter pics/image_xxmrtwigxx_lg.gif diff --git a/images/jumbler starter pics/thumb.gif b/images/jumbler starter pics/thumb.gif Binary files differnew file mode 100644 index 0000000..c321ecb --- /dev/null +++ b/images/jumbler starter pics/thumb.gif diff --git a/locale/org.worldwideworkshop.olpc.SliderPuzzle.pot b/locale/org.worldwideworkshop.olpc.SliderPuzzle.pot new file mode 100644 index 0000000..a396ada --- /dev/null +++ b/locale/org.worldwideworkshop.olpc.SliderPuzzle.pot @@ -0,0 +1,45 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-05-23 23:14+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: SliderPuzzleActivity.py:15 +msgid "SliderPuzzle" +msgstr "" + +#: SliderPuzzleUI.py:91 +msgid "Time: " +msgstr "" + +#: SliderPuzzleUI.py:264 +msgid "Slider Puzzle Activity" +msgstr "" + +#: SliderPuzzleUI.py:298 +msgid "My Own Picture" +msgstr "" + +#: SliderPuzzleUI.py:300 +msgid "Solve" +msgstr "" + +#: SliderPuzzleUI.py:303 +msgid "Jumble" +msgstr "" + +#: SliderPuzzleUI.py:369 +msgid "Select Image Category" +msgstr "" diff --git a/locale/pt/LC_MESSAGES/org.worldwideworkshop.olpc.SliderPuzzle.mo b/locale/pt/LC_MESSAGES/org.worldwideworkshop.olpc.SliderPuzzle.mo Binary files differnew file mode 100644 index 0000000..6bcbcb7 --- /dev/null +++ b/locale/pt/LC_MESSAGES/org.worldwideworkshop.olpc.SliderPuzzle.mo diff --git a/locale/pt/LC_MESSAGES/pt.po b/locale/pt/LC_MESSAGES/pt.po new file mode 100644 index 0000000..0d916cc --- /dev/null +++ b/locale/pt/LC_MESSAGES/pt.po @@ -0,0 +1,49 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-05-23 23:14+0100\n" +"PO-Revision-Date: 2007-05-23 10:48+0100\n" +"Last-Translator: Carlos Neves <cn@sueste>\n" +"Language-Team: Portuguese <info@worldwideworkshop.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: SliderPuzzleActivity.py:15 +msgid "SliderPuzzle" +msgstr "" + +#: SliderPuzzleUI.py:91 +msgid "Time: " +msgstr "Tempo: " + +#: SliderPuzzleUI.py:264 +msgid "Slider Puzzle Activity" +msgstr "" + +#: SliderPuzzleUI.py:298 +msgid "My Own Picture" +msgstr "Minha Imagem" + +#: SliderPuzzleUI.py:300 +msgid "Solve" +msgstr "Resolver" + +#: SliderPuzzleUI.py:303 +msgid "Jumble" +msgstr "Baralhar" + +#: SliderPuzzleUI.py:369 +msgid "Select Image Category" +msgstr "Selecciona a Categoria das Imagens" + +msgid "jumbler starter pics" +msgstr "Imagens iniciais do Jumbler"
\ No newline at end of file diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..7b29315 --- /dev/null +++ b/utils.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + + +### utils +### TODO: Describe +### $Id: $ +### +### author: Carlos Neves (cn (at) sueste.net) +### (c) 2007 World Wide Workshop Foundation + +import pygtk +pygtk.require('2.0') +import gtk + +from math import sqrt, pow, ceil +import sys + +DEBUG = True + +def debug (what): + if DEBUG: + print >> sys.stderr, what + +def calculate_matrix (pieces): + """ Given a number of pieces, calculate the best fit 2 dimensional matrix """ + rows = int(sqrt(pieces)) + cols = int(float(pieces) / rows) + return rows*cols, rows, cols + +def calculate_relative_size (orig_width, orig_height, width, height): + """ If any of width or height is -1, the returned width or height will be in the same relative scale as the + given part. + >>> calculate_relative_size(100, 100, 50, -1) + (50, 50) + >>> calculate_relative_size(200, 100, -1, 50) + (100, 50) + + If both width and height are given, the same values will be returned. If none is given, the orig_* will be returned. + >>> calculate_relative_size(200,200,100,150) + (100, 150) + >>> calculate_relative_size(200,200,-1,-1) + (200, 200) + """ + if width < 0: + if height >= 0: + out_w = int(orig_width * (float(height)/orig_height)) + out_h = height + else: + out_w = orig_width + out_h = orig_height + else: + out_w = width + if height < 0: + out_h = int(orig_height * (float(width)/orig_width)) + else: + out_h = height + return out_w, out_h + +def load_image (filename, width=-1, height=-1): + img = gtk.Image() + img.set_from_file(filename) + pb = img.get_pixbuf() + if pb is None: + return None + w,h = calculate_relative_size(pb.get_width(), pb.get_height(), width, height) + scaled_pb = pb.scale_simple(w,h, gtk.gdk.INTERP_BILINEAR) + return scaled_pb |