Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2012-10-29 12:42:09 (GMT)
committer Walter Bender <walter.bender@gmail.com>2012-10-29 12:42:09 (GMT)
commit94cee3bdd2db050345f042658bdb99097402e7f1 (patch)
treee954e49ad8667d8cf0580d965f456b2a4d37cfe6
parent63fd576111cc9946d718c9accbc654214540a1cb (diff)
parentb1cd00c563c82cdb8a075435e2aa640be4f0dfaa (diff)
Merge git.sugarlabs.org:~walter/visualmatch/walter-gtk3v43
-rw-r--r--NEWS12
-rw-r--r--VisualMatchActivity.py233
-rw-r--r--activity/activity.info3
-rw-r--r--card.py13
-rw-r--r--deck.py3
-rw-r--r--game.py147
-rw-r--r--grid.py15
-rw-r--r--helpbutton.py27
-rwxr-xr-xsetup.py2
-rw-r--r--sprites.py253
-rw-r--r--toolbar_utils.py155
-rwxr-xr-xvisualmatch.py80
12 files changed, 425 insertions, 518 deletions
diff --git a/NEWS b/NEWS
index 708f52d..caf1b2d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,15 @@
+43
+
+BUG FIX:
+* Fixed name change in radio button (#4028)
+
+41
+
+ENHANCEMENTS:
+* GTK-3 version
+* Added summary to activity.info
+* Added support for touch
+
39
BUG FIX:
diff --git a/VisualMatchActivity.py b/VisualMatchActivity.py
index 6557b68..9c249a1 100644
--- a/VisualMatchActivity.py
+++ b/VisualMatchActivity.py
@@ -11,47 +11,33 @@
# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
-import pygtk
-pygtk.require('2.0')
-import gtk
-import gobject
-
-from sugar.activity import activity
-try:
- from sugar.graphics.toolbarbox import ToolbarBox
- _NEW_SUGAR_SYSTEM = True
-except ImportError:
- _NEW_SUGAR_SYSTEM = False
-if _NEW_SUGAR_SYSTEM:
- from sugar.activity.widgets import ActivityToolbarButton
- from sugar.activity.widgets import StopButton
- from sugar.graphics.toolbarbox import ToolbarButton
-from sugar.graphics.alert import NotifyAlert
-from sugar.datastore import datastore
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GObject
+
+from sugar3.activity import activity
+from sugar3 import profile
+from sugar3.graphics.toolbarbox import ToolbarBox
+from sugar3.activity.widgets import ActivityToolbarButton
+from sugar3.activity.widgets import StopButton
+from sugar3.graphics.toolbarbox import ToolbarButton
+from sugar3.graphics.alert import NotifyAlert
+from sugar3.graphics import style
+from sugar3.datastore import datastore
import telepathy
from dbus.service import signal
from dbus.gobject_service import ExportedGObject
-from sugar.presence import presenceservice
-from sugar.presence.tubeconn import TubeConnection
-from sugar.graphics import style
+from sugar3.presence import presenceservice
+from sugar3.presence.tubeconn import TubeConnection
from gettext import gettext as _
import os.path
import logging
_logger = logging.getLogger('visualmatch-activity')
-try:
- _OLD_SUGAR_SYSTEM = False
- import json
- from json import load as jload
- from json import dump as jdump
-except(ImportError, AttributeError):
- try:
- import simplejson as json
- from simplejson import load as jload
- from simplejson import dump as jdump
- except ImportError:
- _OLD_SUGAR_SYSTEM = True
+import json
+from json import load as jload
+from json import dump as jdump
from StringIO import StringIO
@@ -95,7 +81,7 @@ class VisualMatchActivity(activity.Activity):
self.ready_to_play = False
self._prompt = ''
self._read_journal_data()
- self._setup_toolbars(_NEW_SUGAR_SYSTEM)
+ self._setup_toolbars()
canvas = self._setup_canvas()
self._setup_presence_service()
@@ -127,7 +113,7 @@ class VisualMatchActivity(activity.Activity):
return
self._notify_new_game(self._prompt)
# a brief pause to give alert time to load
- timeout = gobject.timeout_add(200, self._new_game, card_type)
+ timeout = GObject.timeout_add(200, self._new_game, card_type)
def _new_game(self, card_type):
if card_type == 'custom' and self.vmw.custom_paths[0] is None:
@@ -255,73 +241,64 @@ class VisualMatchActivity(activity.Activity):
jscores = ''
for i, s in enumerate(self.vmw.all_scores):
jscores += '%s: %s\n' % (str(i + 1), s)
- gtk.Clipboard().set_text(jscores)
+ Gtk.Clipboard().set_text(jscores)
- def _setup_toolbars(self, new_sugar_system):
+ def _setup_toolbars(self):
''' Setup the toolbars.. '''
- games_toolbar = gtk.Toolbar()
- tools_toolbar = gtk.Toolbar()
- numbers_toolbar = gtk.Toolbar()
- if new_sugar_system:
- toolbox = ToolbarBox()
-
- self.activity_toolbar_button = ActivityToolbarButton(self)
-
- toolbox.toolbar.insert(self.activity_toolbar_button, 0)
- self.activity_toolbar_button.show()
-
- self.game_toolbar_button = ToolbarButton(
- page=games_toolbar,
- icon_name='new-game')
- games_toolbar.show()
- toolbox.toolbar.insert(self.game_toolbar_button, -1)
- self.game_toolbar_button.show()
-
- self.numbers_toolbar_button = ToolbarButton(
- page=numbers_toolbar,
- icon_name='number-tools')
- numbers_toolbar.show()
- toolbox.toolbar.insert(self.numbers_toolbar_button, -1)
- self.numbers_toolbar_button.show()
-
- self.tools_toolbar_button = ToolbarButton(
- page=tools_toolbar,
- icon_name='view-source')
- tools_toolbar.show()
- toolbox.toolbar.insert(self.tools_toolbar_button, -1)
- self.tools_toolbar_button.show()
-
- self._set_labels(toolbox.toolbar)
- separator_factory(toolbox.toolbar, True, False)
-
- help_button = HelpButton(self)
- toolbox.toolbar.insert(help_button, -1)
- help_button.show()
- self._setup_toolbar_help()
-
- stop_button = StopButton(self)
- stop_button.props.accelerator = '<Ctrl>q'
- toolbox.toolbar.insert(stop_button, -1)
- stop_button.show()
-
- export_scores = button_factory(
- 'score-copy', self.activity_toolbar_button,
- self._write_scores_to_clipboard,
- tooltip=_('Export scores to clipboard'))
-
- self.set_toolbar_box(toolbox)
- toolbox.show()
-
- self.game_toolbar_button.set_expanded(True)
- else:
- toolbox = activity.ActivityToolbox(self)
- self.set_toolbox(toolbox)
- toolbox.add_toolbar(_('Game'), games_toolbar)
- toolbox.add_toolbar(_('Numbers'), numbers_toolbar)
- toolbox.add_toolbar(_('Tools'), tools_toolbar)
- toolbox.show()
- toolbox.set_current_toolbar(1)
+ games_toolbar = Gtk.Toolbar()
+ tools_toolbar = Gtk.Toolbar()
+ numbers_toolbar = Gtk.Toolbar()
+ toolbox = ToolbarBox()
+
+ self.activity_toolbar_button = ActivityToolbarButton(self)
+
+ toolbox.toolbar.insert(self.activity_toolbar_button, 0)
+ self.activity_toolbar_button.show()
+
+ self.game_toolbar_button = ToolbarButton(
+ page=games_toolbar,
+ icon_name='new-game')
+ games_toolbar.show()
+ toolbox.toolbar.insert(self.game_toolbar_button, -1)
+ self.game_toolbar_button.show()
+
+ self.numbers_toolbar_button = ToolbarButton(
+ page=numbers_toolbar,
+ icon_name='number-tools')
+ numbers_toolbar.show()
+ toolbox.toolbar.insert(self.numbers_toolbar_button, -1)
+ self.numbers_toolbar_button.show()
+
+ self.tools_toolbar_button = ToolbarButton(
+ page=tools_toolbar,
+ icon_name='view-source')
+ tools_toolbar.show()
+ toolbox.toolbar.insert(self.tools_toolbar_button, -1)
+ self.tools_toolbar_button.show()
+
+ self._set_labels(toolbox.toolbar)
+ separator_factory(toolbox.toolbar, True, False)
+
+ help_button = HelpButton(self)
+ toolbox.toolbar.insert(help_button, -1)
+ help_button.show()
+ self._setup_toolbar_help()
+
+ stop_button = StopButton(self)
+ stop_button.props.accelerator = '<Ctrl>q'
+ toolbox.toolbar.insert(stop_button, -1)
+ stop_button.show()
+
+ export_scores = button_factory(
+ 'score-copy', self.activity_toolbar_button,
+ self._write_scores_to_clipboard,
+ tooltip=_('Export scores to clipboard'))
+
+ self.set_toolbar_box(toolbox)
+ toolbox.show()
+
+ self.game_toolbar_button.set_expanded(True)
self.button_pattern = button_factory(
'new-pattern-game', games_toolbar, self._select_game_cb,
@@ -336,11 +313,7 @@ class VisualMatchActivity(activity.Activity):
'no-custom-game', games_toolbar, self._select_game_cb,
cb_arg='custom', tooltip=PROMPT_DICT['custom'])
- if new_sugar_system:
- self._set_extras(games_toolbar, games_toolbar=True)
- else:
- self._set_labels(games_toolbar)
- self._set_extras(tools_toolbar, games_toolbar=False)
+ self._set_extras(games_toolbar)
self.words_tool_button = button_factory(
'word-tools', tools_toolbar, self._edit_words_cb,
@@ -442,9 +415,8 @@ class VisualMatchActivity(activity.Activity):
group=self.hash_button)
NUMBER_C_BUTTONS[LINES] = self.lines_button
- def _set_extras(self, toolbar, games_toolbar=True):
- if games_toolbar:
- separator_factory(toolbar, False, True)
+ def _set_extras(self, toolbar):
+ separator_factory(toolbar, False, True)
self.robot_button = button_factory(
'robot-off', toolbar, self._robot_cb,
tooltip=_('Play with the computer'))
@@ -479,29 +451,25 @@ class VisualMatchActivity(activity.Activity):
group=self.beginner_button)
LEVEL_BUTTONS[EXPERT] = self.expert_button
- self.level_label = label_factory(toolbar, self.calc_level_label(
- self._low_score, self._play_level))
-
- if not games_toolbar:
- separator_factory(toolbar, False, True)
+ self.level_label = label_factory(self.calc_level_label(
+ self._low_score, self._play_level), toolbar)
def _set_labels(self, toolbar):
''' Add labels to toolbar toolbar '''
- self.status_label = label_factory(toolbar, _('Find a match.'))
+ self.status_label = label_factory(_('Find a match.'), toolbar)
separator_factory(toolbar, False, True)
self.deck_label = label_factory(
- toolbar, '%d %s' % (LEVEL_DECKSIZE[self._play_level] - DEAL,
- _('cards')))
+ '%d %s' % (LEVEL_DECKSIZE[self._play_level] - DEAL, _('cards')),
+ toolbar)
separator_factory(toolbar, False, True)
- self.match_label = label_factory(toolbar, '%d %s' % (0, _('matches')))
+ self.match_label = label_factory('%d %s' % (0, _('matches')), toolbar)
separator_factory(toolbar, False, True)
- self.clock_label = label_factory(toolbar, '-')
+ self.clock_label = label_factory('-', toolbar)
def _setup_canvas(self):
''' Create a canvas.. '''
- canvas = gtk.DrawingArea()
- canvas.set_size_request(gtk.gdk.screen_width(),
- gtk.gdk.screen_height())
+ canvas = Gtk.DrawingArea()
+ canvas.set_size_request(Gdk.Screen.width(), Gdk.Screen.height())
self.set_canvas(canvas)
canvas.show()
self.show_all()
@@ -596,12 +564,9 @@ class VisualMatchActivity(activity.Activity):
return self._data_dumper(data)
def _data_dumper(self, data):
- if _OLD_SUGAR_SYSTEM:
- return json.write(data)
- else:
- io = StringIO()
- jdump(data, io)
- return io.getvalue()
+ io = StringIO()
+ jdump(data, io)
+ return io.getvalue()
def read_file(self, file_path):
''' Read data from the Journal. '''
@@ -616,11 +581,8 @@ class VisualMatchActivity(activity.Activity):
self._saved_state = saved_state
def _data_loader(self, data):
- if _OLD_SUGAR_SYSTEM:
- return json.read(data)
- else:
- io = StringIO(data)
- return jload(io)
+ io = StringIO(data)
+ return jload(io)
def _notify_new_game(self, prompt):
''' Called from New Game button since loading a new game can
@@ -637,16 +599,17 @@ class VisualMatchActivity(activity.Activity):
alert.show()
def _new_help_box(self, name, button=None):
- help_box = gtk.VBox()
+ help_box = Gtk.VBox()
help_box.set_homogeneous(False)
help_palettes[name] = help_box
if button is not None:
help_buttons[name] = button
- help_windows[name] = gtk.ScrolledWindow()
+ help_windows[name] = Gtk.ScrolledWindow()
help_windows[name].set_size_request(
- int(gtk.gdk.screen_width() / 3),
- gtk.gdk.screen_height() - style.GRID_CELL_SIZE * 3)
- help_windows[name].set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+ int(Gdk.Screen.width() / 3),
+ Gdk.Screen.height() - style.GRID_CELL_SIZE * 3)
+ help_windows[name].set_policy(Gtk.PolicyType.NEVER,
+ Gtk.PolicyType.AUTOMATIC)
help_windows[name].add_with_viewport(help_palettes[name])
help_palettes[name].show()
return help_box
diff --git a/activity/activity.info b/activity/activity.info
index 99db48a..85b61ef 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -1,9 +1,10 @@
[Activity]
#TRANS: Please translate Visual Match as Dimensions
name = Visual Match
-activity_version = 39
+activity_version = 43
license = GPLv3
bundle_id = org.sugarlabs.VisualMatchActivity
exec = sugar-activity VisualMatchActivity.VisualMatchActivity
icon = activity-visualmatch
show_launcher = yes
+summary = a pattern-matching game
diff --git a/card.py b/card.py
index 69f7f31..c6b4cb6 100644
--- a/card.py
+++ b/card.py
@@ -10,10 +10,7 @@
# along with this library; if not, write to the Free Software
# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
-
-import pygtk
-pygtk.require('2.0')
-import gtk
+from gi.repository import Gdk, GdkPixbuf
import logging
_logger = logging.getLogger('visualmatch-activity')
@@ -74,7 +71,7 @@ class Card:
def svg_str_to_pixbuf(string):
''' Load pixbuf from SVG string '''
- pl = gtk.gdk.PixbufLoader('svg')
+ pl = GdkPixbuf.PixbufLoader.new_with_type('svg')
pl.write(string)
pl.close()
pixbuf = pl.get_pixbuf()
@@ -83,6 +80,6 @@ def svg_str_to_pixbuf(string):
def load_image(object, scale):
''' Load pixbuf from file '''
- return gtk.gdk.pixbuf_new_from_file_at_size(object.file_path,
- int(scale * CARD_WIDTH * .75),
- int(scale * CARD_HEIGHT * .75))
+ return GdkPixbuf.Pixbuf.new_from_file_at_size(
+ object.file_path, int(scale * CARD_WIDTH * .75),
+ int(scale * CARD_HEIGHT * .75))
diff --git a/deck.py b/deck.py
index ca145f3..47573e1 100644
--- a/deck.py
+++ b/deck.py
@@ -10,9 +10,6 @@
# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
-import pygtk
-pygtk.require('2.0')
-import gtk
from random import randrange
from constants import HIGH, MEDIUM, LOW, FILLS, SHAPES, NUMBER, COLORS, \
diff --git a/game.py b/game.py
index 21b6693..0760ca9 100644
--- a/game.py
+++ b/game.py
@@ -13,30 +13,27 @@
# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
-import pygtk
-pygtk.require('2.0')
-import gtk
-import gobject
-
+import gi
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GdkPixbuf
+from gi.repository import GObject
import os
from gettext import gettext as _
from math import sqrt
-from sugar.graphics.objectchooser import ObjectChooser
-from sugar.datastore import datastore
-from sugar import mime
-from sugar.activity import activity
+from sugar3.graphics.objectchooser import ObjectChooser
+from sugar3.datastore import datastore
+from sugar3 import mime
+from sugar3.activity import activity
import logging
_logger = logging.getLogger('visualmatch-activity')
-try:
- from sugar.graphics import style
- GRID_CELL_SIZE = style.GRID_CELL_SIZE
-except ImportError:
- GRID_CELL_SIZE = 0
+from sugar3.graphics import style
+GRID_CELL_SIZE = style.GRID_CELL_SIZE
from constants import LOW, MEDIUM, HIGH, MATCHMASK, ROW, COL, \
WORD_CARD_INDICIES, DEAD_DICTS, DEAD_KEYS, WHITE_SPACE, \
@@ -117,17 +114,19 @@ class Game():
self._canvas = canvas
parent.show_all()
- self._canvas.set_flags(gtk.CAN_FOCUS)
- self._canvas.connect('expose-event', self._expose_cb)
- self._canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK)
- self._canvas.connect('button-press-event', self._button_press_cb)
- self._canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
- self._canvas.connect('button-release-event', self._button_release_cb)
- self._canvas.add_events(gtk.gdk.POINTER_MOTION_MASK)
- self._canvas.connect("motion-notify-event", self._mouse_move_cb)
- self._canvas.connect('key_press_event', self._keypress_cb)
- self._width = gtk.gdk.screen_width()
- self._height = gtk.gdk.screen_height() - GRID_CELL_SIZE
+ self._canvas.set_can_focus(True)
+
+ self._canvas.add_events(Gdk.EventMask.TOUCH_MASK)
+ self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
+ self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
+ self._canvas.add_events(Gdk.EventMask.BUTTON_MOTION_MASK)
+ self._canvas.add_events(Gdk.EventMask.KEY_PRESS_MASK)
+
+ self._canvas.connect('event', self.__event_cb)
+ self._canvas.connect('draw', self.__draw_cb)
+
+ self._width = Gdk.Screen.width()
+ self._height = Gdk.Screen.height() - GRID_CELL_SIZE
self._scale = 0.8 * self._height / (CARD_HEIGHT * 5.5)
self._card_width = CARD_WIDTH * self._scale
self._card_height = CARD_HEIGHT * self._scale
@@ -222,7 +221,7 @@ class Game():
self._saved_state = saved_state
self._deck_index = deck_index
# Wait for any animations to stop before starting new game
- timeout = gobject.timeout_add(200, self._prepare_new_game)
+ timeout = GObject.timeout_add(200, self._prepare_new_game)
def _prepare_new_game(self):
# If there is already a deck, hide it.
@@ -294,11 +293,11 @@ class Game():
if self._game_over():
if hasattr(self, 'timeout_id') and self.timeout_id is not None:
- gobject.source_remove(self.timeout_id)
+ GObject.source_remove(self.timeout_id)
else:
if hasattr(self, 'match_timeout_id') and \
self.match_timeout_id is not None:
- gobject.source_remove(self.match_timeout_id)
+ GObject.source_remove(self.match_timeout_id)
self._timer_reset()
for i in range((ROW - 1) * COL):
@@ -347,7 +346,7 @@ class Game():
self._edit_card = None
self._dead_key = None
if hasattr(self, 'timeout_id') and self.timeout_id is not None:
- gobject.source_remove(self.timeout_id)
+ GObject.source_remove(self.timeout_id)
# Fill the grid with custom cards.
self.grid.restore(self.deck, CUSTOM_CARD_INDICIES)
@@ -376,7 +375,7 @@ class Game():
self._edit_card = None
self._dead_key = None
if hasattr(self, 'timeout_id') and self.timeout_id is not None:
- gobject.source_remove(self.timeout_id)
+ GObject.source_remove(self.timeout_id)
# Fill the grid with word cards.
self.grid.restore(self.deck, WORD_CARD_INDICIES)
self.set_label('deck', '')
@@ -384,10 +383,39 @@ class Game():
self.set_label('clock', '')
self.set_label('status', _('Edit the word cards.'))
+ def __event_cb(self, widget, event):
+ ''' Handle touch events '''
+ if event.type in (Gdk.EventType.TOUCH_BEGIN,
+ Gdk.EventType.TOUCH_END,
+ Gdk.EventType.TOUCH_UPDATE,
+ Gdk.EventType.BUTTON_PRESS,
+ Gdk.EventType.BUTTON_RELEASE,
+ Gdk.EventType.MOTION_NOTIFY):
+ x = event.get_coords()[1]
+ y = event.get_coords()[2]
+ if event.type == Gdk.EventType.TOUCH_BEGIN or \
+ event.type == Gdk.EventType.BUTTON_PRESS:
+ self._button_press(x, y)
+ elif event.type == Gdk.EventType.TOUCH_UPDATE or \
+ event.type == Gdk.EventType.MOTION_NOTIFY:
+ self._drag_event(x, y)
+ elif event.type == Gdk.EventType.TOUCH_END or \
+ event.type == Gdk.EventType.BUTTON_RELEASE:
+ self._button_release(x, y)
+ elif event.type == Gdk.EventType.KEY_PRESS:
+ k = Gdk.keyval_name(event.keyval)
+ u = Gdk.keyval_to_unicode(event.keyval)
+ self._keypress(k, u)
+
def _button_press_cb(self, win, event):
''' Look for a card under the button press and save its position. '''
win.grab_focus()
+ x, y = map(int, event.get_coords())
+ self._button_press(x, y)
+
+ def _button_press(self, x, y):
+
# Turn off help animation
if not self._stop_help:
self._stop_help = True
@@ -402,7 +430,6 @@ class Game():
return True
# Find the sprite under the mouse.
- x, y = map(int, event.get_coords())
spr = self._sprites.find_sprite((x, y))
# If there is a match showing, hide it.
@@ -470,13 +497,16 @@ class Game():
def _mouse_move_cb(self, win, event):
''' Drag the card with the mouse. '''
+ win.grab_focus()
+ x, y = map(int, event.get_coords())
+ self._drag_event(x, y)
+
+ def _drag_event(self, x, y):
if self._press is None or \
self.editing_word_list or \
self.editing_custom_cards:
self._drag_pos = [0, 0]
return True
- win.grab_focus()
- x, y = map(int, event.get_coords())
dx = x - self._drag_pos[0]
dy = y - self._drag_pos[1]
self._press.set_layer(5000)
@@ -486,7 +516,10 @@ class Game():
def _button_release_cb(self, win, event):
''' Lots of possibilities here between clicks and drags '''
win.grab_focus()
+ x, y = map(int, event.get_coords())
+ self._button_release(x, y)
+ def _button_release(self, x, y):
# Maybe there is nothing to do.
if self._press is None:
self._drag_pos = [0, 0]
@@ -495,7 +528,6 @@ class Game():
self._press.set_layer(2000)
# Determine if it was a click, a drag, or an aborted drag
- x, y = map(int, event.get_coords())
d = _distance((x, y), (self._start_pos[0], self._start_pos[1]))
if d < self._card_width / 10: # click
move = 'click'
@@ -722,7 +754,7 @@ match area (%d)' % (i))
for i in range((ROW - 1) * COL):
if self.grid.grid[i] == None:
self._smiley[i].show_card()
- self.match_timeout_id = gobject.timeout_add(
+ self.match_timeout_id = GObject.timeout_add(
2000, self._show_matches, 0)
self._the_game_is_over = True
elif self.grid.cards_in_grid() == DEAL + 3 \
@@ -743,8 +775,8 @@ match area (%d)' % (i))
# Stop the timer.
if hasattr(self, 'timeout_id'):
if self.timeout_id is not None:
- gobject.source_remove(self.timeout_id)
- self.total_time += gobject.get_current_time() - self.start_time
+ GObject.source_remove(self.timeout_id)
+ self.total_time += GObject.get_current_time() - self.start_time
# Increment the match counter and add the match to the match list.
self.matches += 1
@@ -755,7 +787,7 @@ match area (%d)' % (i))
# Test to see if the game is over.
if self._game_over():
if hasattr(self, 'timeout_id'):
- gobject.source_remove(self.timeout_id)
+ GObject.source_remove(self.timeout_id)
if self.low_score[self.level] == -1:
self.low_score[self.level] = self.total_time
elif self.total_time < self.low_score[self.level]:
@@ -773,7 +805,7 @@ match area (%d)' % (i))
else:
# Wait a few seconds before dealing new cards.
self._dealing = True
- gobject.timeout_add(2000, self._deal_new_cards)
+ GObject.timeout_add(2000, self._deal_new_cards)
# Keep playing.
self._update_labels()
@@ -813,8 +845,11 @@ match area (%d)' % (i))
def _keypress_cb(self, area, event):
''' Keypress: editing word cards or selecting cards to play '''
- k = gtk.gdk.keyval_name(event.keyval)
- u = gtk.gdk.keyval_to_unicode(event.keyval)
+ k = Gdk.keyval_name(event.keyval)
+ u = Gdk.keyval_to_unicode(event.keyval)
+ self._keypress(k, u)
+
+ def _keypress(self, k, u):
if self.editing_word_list and self._edit_card is not None:
if k in NOISE_KEYS:
self._dead_key = None
@@ -884,6 +919,9 @@ match area (%d)' % (i))
self.process_selection(self.grid.grid_to_spr(KEYMAP.index(k)))
return True
+ def __draw_cb(self, canvas, cr):
+ self._sprites.redraw_sprites(cr=cr)
+
def _expose_cb(self, win, event):
''' Callback to handle window expose events '''
self.do_expose_event(event)
@@ -906,7 +944,7 @@ match area (%d)' % (i))
def _destroy_cb(self, win, event):
''' This is the end '''
- gtk.main_quit()
+ Gtk.main_quit()
def _update_labels(self):
''' Write strings to a label in the toolbar. '''
@@ -979,16 +1017,16 @@ match area (%d)' % (i))
def _counter(self):
''' Display of seconds since start_time. '''
- seconds = int(gobject.get_current_time() - self.start_time)
+ seconds = int(GObject.get_current_time() - self.start_time)
self.set_label('clock', str(seconds))
if self.robot and self.robot_time < seconds:
self._find_a_match(robot_match=True)
else:
- self.timeout_id = gobject.timeout_add(1000, self._counter)
+ self.timeout_id = GObject.timeout_add(1000, self._counter)
def _timer_reset(self):
''' Reset the timer for the robot '''
- self.start_time = gobject.get_current_time()
+ self.start_time = GObject.get_current_time()
self.timeout_id = None
self._counter()
@@ -999,7 +1037,7 @@ match area (%d)' % (i))
for j in range(CARDS_IN_A_MATCH):
self.grid.display_match(
self.match_list[i * CARDS_IN_A_MATCH + j], j)
- self.match_timeout_id = gobject.timeout_add(
+ self.match_timeout_id = GObject.timeout_add(
2000, self._show_matches, i + 1)
def _find_a_match(self, robot_match=False):
@@ -1008,7 +1046,7 @@ match area (%d)' % (i))
if self._matches_on_display:
if not self.deck.empty():
self._matches_on_display = False
- gobject.timeout_add(1000, self.clean_up_match)
+ GObject.timeout_add(1000, self.clean_up_match)
else:
for c in self.clicked:
if c.spr is not None:
@@ -1096,13 +1134,14 @@ match area (%d)' % (i))
try:
chooser = ObjectChooser(parent=self, what_filter=None)
except TypeError:
- chooser = ObjectChooser(None, self.activity,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
+ chooser = ObjectChooser(
+ None, self.activity,
+ Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT)
if chooser is not None:
try:
result = chooser.run()
- if result == gtk.RESPONSE_ACCEPT:
+ if result == Gtk.ResponseType.ACCEPT:
jobject = chooser.get_selected_object()
if jobject and jobject.file_path:
name = jobject.metadata['title']
@@ -1188,7 +1227,7 @@ match area (%d)' % (i))
self._help_index = 0
self._stop_help = False
self._help[self._help_index].set_layer(5000)
- self._help_timeout_id = gobject.timeout_add(2000, self._help_next)
+ self._help_timeout_id = GObject.timeout_add(2000, self._help_next)
def _help_next(self):
''' Load the next frame in the animation '''
@@ -1200,9 +1239,9 @@ match area (%d)' % (i))
self._help_index %= len(self._help)
self._help[self._help_index].set_layer(5000)
if self._help_index in [0, 9, 10, 20, 21]:
- self._help_timeout_id = gobject.timeout_add(2000, self._help_next)
+ self._help_timeout_id = GObject.timeout_add(2000, self._help_next)
else:
- self._help_timeout_id = gobject.timeout_add(1000, self._help_next)
+ self._help_timeout_id = GObject.timeout_add(1000, self._help_next)
class Permutation:
@@ -1229,7 +1268,7 @@ class Permutation:
def svg_str_to_pixbuf(svg_string, w, h):
""" Load pixbuf from SVG string """
- pl = gtk.gdk.PixbufLoader('svg')
+ pl = GdkPixbuf.PixbufLoader.new_with_type('svg')
pl.set_size(w, h)
pl.write(svg_string)
pl.close()
diff --git a/grid.py b/grid.py
index f9b0900..03e2078 100644
--- a/grid.py
+++ b/grid.py
@@ -10,10 +10,7 @@
# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
-import pygtk
-pygtk.require('2.0')
-import gtk
-import gobject
+from gi.repository import GObject
import random
@@ -105,7 +102,7 @@ class Grid:
i = self.find_an_empty_slot()
# Put new card in grid position of card we are replacing.
self.grid[i] = deck.deal_next_card()
- timeout_id = gobject.timeout_add(
+ timeout_id = GObject.timeout_add(
1200, self.place_a_card, self.grid[i],
self.grid_to_xy(i)[0], self.grid_to_xy(i)[1], j)
@@ -119,7 +116,7 @@ class Grid:
self.sy[i] = spr.get_xy()[1]
self.dx[i] = int((self.ex[i] - self.sx[i]) / 10)
self.dy[i] = int((self.ey[i] - self.sy[i]) / 10)
- timeout_id = gobject.timeout_add(
+ timeout_id = GObject.timeout_add(
100, self._move_to_position, spr, i)
def return_to_grid(self, spr, i, j):
@@ -133,7 +130,7 @@ class Grid:
self.sy[j] = spr.get_xy()[1]
self.dx[j] = int((self.ex[j] - self.sx[j]) / 10)
self.dy[j] = int((self.ey[j] - self.sy[j]) / 10)
- timeout_id = gobject.timeout_add(
+ timeout_id = GObject.timeout_add(
100, self._move_to_position, spr, j)
def _move_to_position(self, spr, i):
@@ -146,7 +143,7 @@ class Grid:
spr.move((self.ex[i], self.ey[i]))
self.animation_lock[i] = False
else:
- timeout_id = gobject.timeout_add(
+ timeout_id = GObject.timeout_add(
100, self._move_to_position, spr, i)
def consolidate(self):
@@ -180,7 +177,7 @@ class Grid:
self.dy[animate + 3] = int(
(self.ey[animate + 3] - c.spr.get_xy()[1]) / 10)
self.animation_lock[animate + 3] = True
- timeout_id = gobject.timeout_add(100, self._move_to_position,
+ timeout_id = GObject.timeout_add(100, self._move_to_position,
c.spr, animate + 3)
def xy_to_match(self, pos):
diff --git a/helpbutton.py b/helpbutton.py
index 6c4540b..cea6110 100644
--- a/helpbutton.py
+++ b/helpbutton.py
@@ -21,11 +21,12 @@
from gettext import gettext as _
-import gtk
+from gi.repository import Gtk
+from gi.repository import Gdk
-from sugar.graphics.toolbutton import ToolButton
-from sugar.graphics.icon import Icon
-from sugar.graphics import style
+from sugar3.graphics.toolbutton import ToolButton
+from sugar3.graphics.icon import Icon
+from sugar3.graphics import style
help_windows = {}
help_buttons = {}
@@ -34,13 +35,13 @@ import logging
_logger = logging.getLogger('visualmatch-activity')
-class HelpButton(gtk.ToolItem):
+class HelpButton(Gtk.ToolItem):
def __init__(self, activity):
self._activity = activity
self._current_palette = 'game'
- gtk.ToolItem.__init__(self)
+ Gtk.ToolItem.__init__(self)
help_button = ToolButton('help-toolbar')
help_button.set_tooltip(_('Help'))
@@ -85,9 +86,9 @@ class HelpButton(gtk.ToolItem):
def add_section(help_box, section_text, icon=None):
''' Add a section to the help palette. From helpbutton.py by
Gonzalo Odiard '''
- max_text_width = int(gtk.gdk.screen_width() / 3) - 20
- hbox = gtk.HBox()
- label = gtk.Label()
+ max_text_width = int(Gdk.Screen.width() / 3) - 20
+ hbox = Gtk.HBox()
+ label = Gtk.Label()
label.set_use_markup(True)
label.set_markup('<b>%s</b>' % section_text)
label.set_line_wrap(True)
@@ -107,10 +108,10 @@ def add_section(help_box, section_text, icon=None):
def add_paragraph(help_box, text, icon=None):
''' Add an entry to the help palette. From helpbutton.py by
Gonzalo Odiard '''
- max_text_width = int(gtk.gdk.screen_width() / 3) - 20
- hbox = gtk.HBox()
- label = gtk.Label(text)
- label.set_justify(gtk.JUSTIFY_LEFT)
+ max_text_width = int(Gdk.Screen.width() / 3) - 20
+ hbox = Gtk.HBox()
+ label = Gtk.Label(label=text)
+ label.set_justify(Gtk.Justification.LEFT)
label.set_line_wrap(True)
hbox.add(label)
if icon is not None:
diff --git a/setup.py b/setup.py
index bd1e319..bdeaed6 100755
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-from sugar.activity import bundlebuilder
+from sugar3.activity import bundlebuilder
if __name__ == "__main__":
bundlebuilder.start()
diff --git a/sprites.py b/sprites.py
index 8e4c8c5..e128369 100644
--- a/sprites.py
+++ b/sprites.py
@@ -24,7 +24,7 @@
'''
sprites.py is a simple sprites library for managing graphics objects,
-'sprites', on a gtk.DrawingArea. It manages multiple sprites with
+'sprites', on a Gtk.DrawingArea. It manages multiple sprites with
methods such as move, hide, set_layer, etc.
There are two classes:
@@ -68,7 +68,7 @@ Example usage:
# method for converting SVG to a gtk pixbuf
def svg_str_to_pixbuf(svg_string):
- pl = gtk.gdk.PixbufLoader('svg')
+ pl = GdkPixbuf.PixbufLoader('svg')
pl.write(svg_string)
pl.close()
pixbuf = pl.get_pixbuf()
@@ -76,12 +76,9 @@ def svg_str_to_pixbuf(svg_string):
'''
-import pygtk
-pygtk.require('2.0')
-import gtk
-import pango
-import pangocairo
-import cairo
+import gi
+from gi.repository import Gtk, GdkPixbuf, Gdk
+from gi.repository import Pango, PangoCairo
class Sprites:
@@ -89,9 +86,9 @@ class Sprites:
def __init__(self, widget):
''' Initialize an empty array of sprites '''
+ self.cr = None
self.widget = widget
self.list = []
- self.cr = None
def set_cairo_context(self, cr):
''' Cairo context may be set or reset after __init__ '''
@@ -99,7 +96,7 @@ class Sprites:
def get_sprite(self, i):
''' Return a sprint from the array '''
- if i < 0 or i > len(self.list) - 1:
+ if i < 0 or i > len(self.list)-1:
return(None)
else:
return(self.list[i])
@@ -121,23 +118,17 @@ class Sprites:
else:
self.list.insert(i, spr)
- def find_in_list(self, spr):
- if spr in self.list:
- return True
- return False
-
def remove_from_list(self, spr):
''' Remove a sprite from the list. '''
if spr in self.list:
self.list.remove(spr)
- def find_sprite(self, pos, region=False, reverse=False):
+ def find_sprite(self, pos):
''' Search based on (x, y) position. Return the 'top/first' one. '''
list = self.list[:]
- if not reverse:
- list.reverse()
+ list.reverse()
for spr in list:
- if spr.hit(pos, readpixel=not region):
+ if spr.hit(pos):
return spr
return None
@@ -149,7 +140,7 @@ class Sprites:
else:
self.cr = cr
if cr is None:
- # print 'sprites.redraw_sprites: no Cairo context'
+ print 'sprites.redraw_sprites: no Cairo context'
return
for spr in self.list:
if area == None:
@@ -166,8 +157,7 @@ class Sprite:
def __init__(self, sprites, x, y, image):
''' Initialize an individual sprite '''
self._sprites = sprites
- self.save_xy = (x, y) # remember initial (x, y) position
- self.rect = gtk.gdk.Rectangle(int(x), int(y), 0, 0)
+ self.rect = [int(x), int(y), 0, 0]
self._scale = [12]
self._rescale = [True]
self._horiz_align = ["center"]
@@ -179,7 +169,7 @@ class Sprite:
self._margins = [0, 0, 0, 0]
self.layer = 100
self.labels = []
- self.cached_surfaces = []
+ self.images = []
self._dx = [] # image offsets
self._dy = []
self.type = None
@@ -188,58 +178,47 @@ class Sprite:
def set_image(self, image, i=0, dx=0, dy=0):
''' Add an image to the sprite. '''
- while len(self.cached_surfaces) < i + 1:
- self.cached_surfaces.append(None)
+ while len(self.images) < i + 1:
+ self.images.append(None)
self._dx.append(0)
self._dy.append(0)
+ self.images[i] = image
self._dx[i] = dx
self._dy[i] = dy
- if isinstance(image, gtk.gdk.Pixbuf) or \
- isinstance(image, cairo.ImageSurface):
- w = image.get_width()
- h = image.get_height()
+ if isinstance(self.images[i], GdkPixbuf.Pixbuf):
+ w = self.images[i].get_width()
+ h = self.images[i].get_height()
else:
- w, h = image.get_size()
+ w, h = self.images[i].get_size()
if i == 0: # Always reset width and height when base image changes.
- self.rect.width = w + dx
- self.rect.height = h + dy
+ self.rect[2] = w + dx
+ self.rect[3] = h + dy
else:
- if w + dx > self.rect.width:
- self.rect.width = w + dx
- if h + dy > self.rect.height:
- self.rect.height = h + dy
- if isinstance(image, cairo.ImageSurface):
- self.cached_surfaces[i] = image
- else: # Convert to Cairo surface
- surface = cairo.ImageSurface(
- cairo.FORMAT_ARGB32, self.rect.width, self.rect.height)
- context = cairo.Context(surface)
- context = gtk.gdk.CairoContext(context)
- context.set_source_pixbuf(image, 0, 0)
- context.rectangle(0, 0, self.rect.width, self.rect.height)
- context.fill()
- self.cached_surfaces[i] = surface
+ if w + dx > self.rect[2]:
+ self.rect[2] = w + dx
+ if h + dy > self.rect[3]:
+ self.rect[3] = h + dy
def move(self, pos):
''' Move to new (x, y) position '''
self.inval()
- self.rect.x, self.rect.y = int(pos[0]), int(pos[1])
+ self.rect[0], self.rect[1] = int(pos[0]), int(pos[1])
self.inval()
def move_relative(self, pos):
''' Move to new (x+dx, y+dy) position '''
self.inval()
- self.rect.x += int(pos[0])
- self.rect.y += int(pos[1])
+ self.rect[0] += int(pos[0])
+ self.rect[1] += int(pos[1])
self.inval()
def get_xy(self):
''' Return current (x, y) position '''
- return (self.rect.x, self.rect.y)
+ return (self.rect[0], self.rect[1])
def get_dimensions(self):
''' Return current size '''
- return (self.rect.width, self.rect.height)
+ return (self.rect[2], self.rect[3])
def get_layer(self):
''' Return current layer '''
@@ -251,11 +230,10 @@ class Sprite:
self.set_image(image, i)
self.inval()
- def set_layer(self, layer=None):
+ def set_layer(self, layer):
''' Set the layer for a sprite '''
self._sprites.remove_from_list(self)
- if layer is not None:
- self.layer = layer
+ self.layer = layer
for i in range(self._sprites.length_of_list()):
if layer < self._sprites.get_sprite(i).layer:
self._sprites.insert_in_list(self, i)
@@ -283,7 +261,7 @@ class Sprite:
if self._fd is None:
self.set_font('Sans')
if self._color is None:
- self._color = (0., 0., 0.)
+ self._color = (0.5, 0.5, 0.5)
while len(self.labels) < i + 1:
self.labels.append(" ")
self._scale.append(self._scale[0])
@@ -293,7 +271,7 @@ class Sprite:
def set_font(self, font):
''' Set the font for a label '''
- self._fd = pango.FontDescription(font)
+ self._fd = Pango.FontDescription(font)
def set_label_color(self, rgb):
''' Set the font color for a label '''
@@ -324,145 +302,136 @@ class Sprite:
self.inval()
self._sprites.remove_from_list(self)
- def restore(self):
- ''' Restore a hidden sprite '''
- self.set_layer()
-
def inval(self):
''' Invalidate a region for gtk '''
- self._sprites.widget.queue_draw_area(self.rect.x,
- self.rect.y,
- self.rect.width,
- self.rect.height)
+ # self._sprites.window.invalidate_rect(self.rect, False)
+ self._sprites.widget.queue_draw_area(self.rect[0],
+ self.rect[1],
+ self.rect[2],
+ self.rect[3])
def draw(self, cr=None):
''' Draw the sprite (and label) '''
if cr is None:
- # print 'sprite.draw: no Cairo context.'
+ cr = self._sprites.cr
+ if cr is None:
+ print 'sprite.draw: no Cairo context.'
return
- for i, surface in enumerate(self.cached_surfaces):
- cr.set_source_surface(surface,
- self.rect.x + self._dx[i],
- self.rect.y + self._dy[i])
- cr.rectangle(self.rect.x + self._dx[i],
- self.rect.y + self._dy[i],
- self.rect.width,
- self.rect.height)
- cr.fill()
+ for i, img in enumerate(self.images):
+ if isinstance(img, GdkPixbuf.Pixbuf):
+ Gdk.cairo_set_source_pixbuf(cr, img,
+ self.rect[0] + self._dx[i],
+ self.rect[1] + self._dy[i])
+ cr.rectangle(self.rect[0] + self._dx[i],
+ self.rect[1] + self._dy[i],
+ self.rect[2],
+ self.rect[3])
+ cr.fill()
+ else:
+ print 'sprite.draw: source not a pixbuf (%s)' % (type(img))
if len(self.labels) > 0:
self.draw_label(cr)
- def hit(self, pos, readpixel=False):
+ def hit(self, pos):
''' Is (x, y) on top of the sprite? '''
x, y = pos
- if x < self.rect.x:
+ if x < self.rect[0]:
return False
- if x > self.rect.x + self.rect.width:
+ if x > self.rect[0] + self.rect[2]:
return False
- if y < self.rect.y:
+ if y < self.rect[1]:
return False
- if y > self.rect.y + self.rect.height:
+ if y > self.rect[1] + self.rect[3]:
return False
- if readpixel:
- r, g, b, a = self.get_pixel(pos)
- if r == g == b == a == 0:
- return False
- if a == -1:
- return False
- return self._sprites.find_in_list(self)
+ return True
def draw_label(self, cr):
''' Draw the label based on its attributes '''
- # Create a pangocairo context
- cr = pangocairo.CairoContext(cr)
- my_width = self.rect.width - self._margins[0] - self._margins[2]
+ my_width = self.rect[2] - self._margins[0] - self._margins[2]
if my_width < 0:
my_width = 0
- my_height = self.rect.height - self._margins[1] - self._margins[3]
+ my_height = self.rect[3] - self._margins[1] - self._margins[3]
for i in range(len(self.labels)):
- pl = cr.create_layout()
- pl.set_text(str(self.labels[i]))
- self._fd.set_size(int(self._scale[i] * pango.SCALE))
+ pl = PangoCairo.create_layout(cr)
+ pl.set_text(str(self.labels[i]), -1)
+ self._fd.set_size(int(self._scale[i] * Pango.SCALE))
pl.set_font_description(self._fd)
- w = pl.get_size()[0] / pango.SCALE
+ w = pl.get_size()[0] / Pango.SCALE
if w > my_width:
if self._rescale[i]:
self._fd.set_size(
- int(self._scale[i] * pango.SCALE * my_width / w))
+ int(self._scale[i] * Pango.SCALE * my_width / w))
pl.set_font_description(self._fd)
- w = pl.get_size()[0] / pango.SCALE
+ w = pl.get_size()[0] / Pango.SCALE
else:
j = len(self.labels[i]) - 1
while(w > my_width and j > 0):
pl.set_text(
- "…" + self.labels[i][len(self.labels[i]) - j:])
- self._fd.set_size(int(self._scale[i] * pango.SCALE))
+ "…" + self.labels[i][len(self.labels[i]) - j:], -1)
+ self._fd.set_size(int(self._scale[i] * Pango.SCALE))
pl.set_font_description(self._fd)
- w = pl.get_size()[0] / pango.SCALE
+ w = pl.get_size()[0] / Pango.SCALE
j -= 1
if self._horiz_align[i] == "center":
- x = int(self.rect.x + self._margins[0] + (my_width - w) / 2)
+ x = int(self.rect[0] + self._margins[0] + (my_width - w) / 2)
elif self._horiz_align[i] == 'left':
- x = int(self.rect.x + self._margins[0])
- else: # right
- x = int(self.rect.x + self.rect.width - w - self._margins[2])
- h = pl.get_size()[1] / pango.SCALE
+ x = int(self.rect[0] + self._margins[0])
+ else: # right
+ x = int(self.rect[0] + self.rect[2] - w - self._margins[2])
+ h = pl.get_size()[1] / Pango.SCALE
if self._vert_align[i] == "middle":
- y = int(self.rect.y + self._margins[1] + (my_height - h) / 2)
+ y = int(self.rect[1] + self._margins[1] + (my_height - h) / 2)
elif self._vert_align[i] == "top":
- y = int(self.rect.y + self._margins[1])
- else: # bottom
- y = int(self.rect.y + self.rect.height - h - self._margins[3])
+ y = int(self.rect[1] + self._margins[1])
+ else: # bottom
+ y = int(self.rect[1] + self.rect[3] - h - self._margins[3])
cr.save()
cr.translate(x, y)
cr.set_source_rgb(self._color[0], self._color[1], self._color[2])
- cr.update_layout(pl)
- cr.show_layout(pl)
+ PangoCairo.update_layout(cr, pl)
+ PangoCairo.show_layout(cr, pl)
cr.restore()
def label_width(self):
''' Calculate the width of a label '''
- cr = pangocairo.CairoContext(self._sprites.cr)
- if cr is not None:
- max = 0
- for i in range(len(self.labels)):
- pl = cr.create_layout()
- pl.set_text(self.labels[i])
- self._fd.set_size(int(self._scale[i] * pango.SCALE))
- pl.set_font_description(self._fd)
- w = pl.get_size()[0] / pango.SCALE
- if w > max:
- max = w
- return max
- else:
- return self.rect.width
+ max = 0
+ for i in range(len(self.labels)):
+ pl = self._sprites.canvas.create_pango_layout(self.labels[i])
+ self._fd.set_size(int(self._scale[i] * Pango.SCALE))
+ pl.set_font_description(self._fd)
+ w = pl.get_size()[0] / Pango.SCALE
+ if w > max:
+ max = w
+ return max
def label_safe_width(self):
''' Return maximum width for a label '''
- return self.rect.width - self._margins[0] - self._margins[2]
+ return self.rect[2] - self._margins[0] - self._margins[2]
def label_safe_height(self):
''' Return maximum height for a label '''
- return self.rect.height - self._margins[1] - self._margins[3]
+ return self.rect[3] - self._margins[1] - self._margins[3]
def label_left_top(self):
''' Return the upper-left corner of the label safe zone '''
return(self._margins[0], self._margins[1])
def get_pixel(self, pos, i=0):
- ''' Return the pixel at (x, y) '''
- x = int(pos[0] - self.rect.x)
- y = int(pos[1] - self.rect.y)
- if x < 0 or x > (self.rect.width - 1) or \
- y < 0 or y > (self.rect.height - 1):
+ ''' Return the pixl at (x, y) '''
+ x, y = pos
+ x = x - self.rect[0]
+ y = y - self.rect[1]
+ if y > self.images[i].get_height() - 1:
+ return(-1, -1, -1, -1)
+ try:
+ array = self.images[i].get_pixels()
+ if array is not None:
+ offset = (y * self.images[i].get_width() + x) * 4
+ r, g, b, a = ord(array[offset]), ord(array[offset + 1]),\
+ ord(array[offset + 2]), ord(array[offset + 3])
+ return(r, g, b, a)
+ else:
+ return(-1, -1, -1, -1)
+ except IndexError:
+ print "Index Error: %d %d" % (len(array), offset)
return(-1, -1, -1, -1)
- # Create a new 1x1 cairo surface.
- cs = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
- cr = cairo.Context(cs)
- cr.set_source_surface(self.cached_surfaces[i], -x, -y)
- cr.rectangle(0, 0, 1, 1)
- cr.set_operator(cairo.OPERATOR_SOURCE)
- cr.fill()
- cs.flush() # Ensure all the writing is done.
- pixels = cs.get_data() # Read the pixel.
- return (ord(pixels[2]), ord(pixels[1]), ord(pixels[0]), 0)
diff --git a/toolbar_utils.py b/toolbar_utils.py
index 94e6883..607bf22 100644
--- a/toolbar_utils.py
+++ b/toolbar_utils.py
@@ -11,70 +11,25 @@
# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
-import gtk
+from gi.repository import Gtk
-from sugar.graphics.radiotoolbutton import RadioToolButton
-from sugar.graphics.toolbutton import ToolButton
-from sugar.graphics.combobox import ComboBox
-from sugar.graphics.toolcombobox import ToolComboBox
-
-
-def combo_factory(combo_array, toolbar, callback, cb_arg=None,
- tooltip=None, default=None):
- '''Factory for making a toolbar combo box'''
- combo = ComboBox()
- if tooltip is not None and hasattr(combo, 'set_tooltip_text'):
- combo.set_tooltip_text(tooltip)
- if cb_arg is not None:
- combo.connect('changed', callback, cb_arg)
- else:
- combo.connect('changed', callback)
- for i, selection in enumerate(combo_array):
- combo.append_item(i, selection, None)
- combo.show()
- toolitem = gtk.ToolItem()
- toolitem.add(combo)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- if default is not None:
- combo.set_active(combo_array.index(default))
- return combo
-
-
-def entry_factory(default_string, toolbar, tooltip=None, max=3):
- ''' Factory for adding a text box to a toolbar '''
- entry = gtk.Entry()
- entry.set_text(default_string)
- if tooltip is not None and hasattr(entry, 'set_tooltip_text'):
- entry.set_tooltip_text(tooltip)
- entry.set_width_chars(max)
- entry.show()
- toolitem = gtk.ToolItem()
- toolitem.add(entry)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- return entry
+from sugar3.graphics.toolbutton import ToolButton
+from sugar3.graphics.radiotoolbutton import RadioToolButton
def button_factory(icon_name, toolbar, callback, cb_arg=None, tooltip=None,
- accelerator=None):
- '''Factory for making tooplbar buttons'''
+ accelerator=None):
+ ''' Factory for making toolbar buttons '''
button = ToolButton(icon_name)
if tooltip is not None:
button.set_tooltip(tooltip)
button.props.sensitive = True
if accelerator is not None:
button.props.accelerator = accelerator
- if cb_arg is not None:
- button.connect('clicked', callback, cb_arg)
- else:
+ if cb_arg is None:
button.connect('clicked', callback)
+ else:
+ button.connect('clicked', callback, cb_arg)
if hasattr(toolbar, 'insert'): # the main toolbar
toolbar.insert(button, -1)
else: # or a secondary toolbar
@@ -83,82 +38,60 @@ def button_factory(icon_name, toolbar, callback, cb_arg=None, tooltip=None,
return button
-def radio_factory(name, toolbar, callback, cb_arg=None, tooltip=None,
- group=None):
+def radio_factory(icon_name, toolbar, callback, cb_arg=None,
+ tooltip=None, group=None):
''' Add a radio button to a toolbar '''
button = RadioToolButton(group=group)
- button.set_named_icon(name)
- if callback is not None:
- if cb_arg is None:
- button.connect('clicked', callback)
- else:
- button.connect('clicked', callback, cb_arg)
- if hasattr(toolbar, 'insert'): # Add button to the main toolbar...
+ button.set_icon_name(icon_name)
+ if tooltip is not None:
+ button.set_tooltip(tooltip)
+ if cb_arg is None:
+ button.connect('clicked', callback)
+ else:
+ button.connect('clicked', callback, cb_arg)
+ if hasattr(toolbar, 'insert'): # the main toolbar
toolbar.insert(button, -1)
- else: # ...or a secondary toolbar.
+ else: # or a secondary toolbar
toolbar.props.page.insert(button, -1)
button.show()
- if tooltip is not None:
- button.set_tooltip(tooltip)
return button
-def label_factory(toolbar, label_text, width=None):
+def label_factory(label_text, toolbar):
''' Factory for adding a label to a toolbar '''
- label = gtk.Label(label_text)
+ label = Gtk.Label(label=label_text)
label.set_line_wrap(True)
- if width is not None:
- label.set_size_request(width, -1) # doesn't work on XOs
label.show()
- toolitem = gtk.ToolItem()
+ toolitem = Gtk.ToolItem()
toolitem.add(label)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(toolitem, -1)
+ toolbar.insert(toolitem, -1)
toolitem.show()
return label
-def separator_factory(toolbar, expand=False, visible=True):
- ''' add a separator to a toolbar '''
- separator = gtk.SeparatorToolItem()
- separator.props.draw = visible
- separator.set_expand(expand)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(separator, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(separator, -1)
- separator.show()
-
-
-def image_factory(image, toolbar, tooltip=None):
- ''' Add an image to the toolbar '''
- img = gtk.Image()
- img.set_from_pixbuf(image)
- img_tool = gtk.ToolItem()
- img_tool.add(img)
- if tooltip is not None:
- img.set_tooltip_text(tooltip)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(img_tool, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(img_tool, -1)
- img_tool.show()
- return img
-
-
-def spin_factory(default, min, max, callback, toolbar):
- spin_adj = gtk.Adjustment(default, min, max, 1, 32, 0)
- spin = gtk.SpinButton(spin_adj, 0, 0)
- spin_id = spin.connect('value-changed', callback)
+def spin_factory(default, min_value, max_value, callback, toolbar):
+ ''' Factory for making toolbar value spinners '''
+ spin_adj = Gtk.Adjustment(default, min_value, max_value, 1, 32, 0)
+ spin = Gtk.SpinButton()
+ spin.set_adjustment(spin_adj)
+ spin.connect('value-changed', callback)
spin.set_numeric(True)
spin.show()
- toolitem = gtk.ToolItem()
+ toolitem = Gtk.ToolItem()
toolitem.add(spin)
- if hasattr(toolbar, 'insert'): # the main toolbar
+ if toolbar is not None:
toolbar.insert(toolitem, -1)
+ toolitem.show()
+ return spin
else:
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- return spin
+ toolitem.show()
+ return spin, toolitem
+
+
+def separator_factory(toolbar, expand=False, visible=True):
+ ''' Add a separator to a toolbar '''
+ separator = Gtk.SeparatorToolItem()
+ separator.props.draw = visible
+ separator.set_expand(expand)
+ toolbar.insert(separator, -1)
+ separator.show()
diff --git a/visualmatch.py b/visualmatch.py
index 809f556..3fa1211 100755
--- a/visualmatch.py
+++ b/visualmatch.py
@@ -12,9 +12,9 @@
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
-import pygtk
-pygtk.require('2.0')
-import gtk
+import gi
+from gi.repository import Gtk
+from gi.repository import Gdk
from gettext import gettext as _
import os
@@ -27,130 +27,128 @@ from constants import PRODUCT, HASH, ROMAN, WORD, CHINESE, MAYAN, DICE, DOTS, \
class VisualMatchMain:
def __init__(self):
- self.r = 0
- self.tw = None
# create a new window
- self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ self.win = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
self.win.maximize()
self.win.set_title("%s: %s" % (_("Visual Match"),
_("Click on cards to create sets of three.")))
- self.win.connect("delete_event", lambda w, e: gtk.main_quit())
+ self.win.connect("delete_event", lambda w, e: Gtk.main_quit())
- menu0 = gtk.Menu()
- menu_items = gtk.MenuItem(_("Toggle level"))
+ menu0 = Gtk.Menu()
+ menu_items = Gtk.MenuItem(_("Toggle level"))
menu0.append(menu_items)
menu_items.connect("activate", self._level_cb)
menu_items.show()
- level_menu = gtk.MenuItem("Level")
+ level_menu = Gtk.MenuItem("Level")
level_menu.show()
level_menu.set_submenu(menu0)
- menu1 = gtk.Menu()
- menu_items = gtk.MenuItem(_("New pattern game"))
+ menu1 = Gtk.Menu()
+ menu_items = Gtk.MenuItem(_("New pattern game"))
menu1.append(menu_items)
menu_items.connect("activate", self._new_game_cb, 'pattern')
menu_items.show()
- menu_items = gtk.MenuItem(_("New number game"))
+ menu_items = Gtk.MenuItem(_("New number game"))
menu1.append(menu_items)
menu_items.connect("activate", self._new_game_cb, 'number')
menu_items.show()
- menu_items = gtk.MenuItem(_("New word game"))
+ menu_items = Gtk.MenuItem(_("New word game"))
menu1.append(menu_items)
menu_items.connect("activate", self._new_game_cb, 'word')
menu_items.show()
- game_menu = gtk.MenuItem("Games")
+ game_menu = Gtk.MenuItem("Games")
game_menu.show()
game_menu.set_submenu(menu1)
- menu2 = gtk.Menu()
- menu_items = gtk.MenuItem(_("Robot on/off"))
+ menu2 = Gtk.Menu()
+ menu_items = Gtk.MenuItem(_("Robot on/off"))
menu2.append(menu_items)
menu_items.connect("activate", self._robot_cb)
menu_items.show()
- menu_items = gtk.MenuItem(_("90 sec."))
+ menu_items = Gtk.MenuItem(_("90 sec."))
menu2.append(menu_items)
menu_items.connect("activate", self._robot_time_cb, 90)
menu_items.show()
- menu_items = gtk.MenuItem(_("60 sec."))
+ menu_items = Gtk.MenuItem(_("60 sec."))
menu2.append(menu_items)
menu_items.connect("activate", self._robot_time_cb, 60)
menu_items.show()
- menu_items = gtk.MenuItem(_("45 sec."))
+ menu_items = Gtk.MenuItem(_("45 sec."))
menu2.append(menu_items)
menu_items.connect("activate", self._robot_time_cb, 45)
menu_items.show()
- menu_items = gtk.MenuItem(_("30 sec."))
+ menu_items = Gtk.MenuItem(_("30 sec."))
menu2.append(menu_items)
menu_items.connect("activate", self._robot_time_cb, 30)
menu_items.show()
- menu_items = gtk.MenuItem(_("15 sec."))
+ menu_items = Gtk.MenuItem(_("15 sec."))
menu2.append(menu_items)
menu_items.connect("activate", self._robot_time_cb, 15)
menu_items.show()
- tool_menu = gtk.MenuItem("Robot")
+ tool_menu = Gtk.MenuItem("Robot")
tool_menu.show()
tool_menu.set_submenu(menu2)
- menu3 = gtk.Menu()
- menu_items = gtk.MenuItem(_("Product"))
+ menu3 = Gtk.Menu()
+ menu_items = Gtk.MenuItem(_("Product"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_O_cb, PRODUCT)
menu_items.show()
- menu_items = gtk.MenuItem(_("Roman"))
+ menu_items = Gtk.MenuItem(_("Roman"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_O_cb, ROMAN)
menu_items.show()
- menu_items = gtk.MenuItem(_("Word"))
+ menu_items = Gtk.MenuItem(_("Word"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_O_cb, WORD)
menu_items.show()
- menu_items = gtk.MenuItem(_("Chinese"))
+ menu_items = Gtk.MenuItem(_("Chinese"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_O_cb, CHINESE)
menu_items.show()
- menu_items = gtk.MenuItem(_("Mayan"))
+ menu_items = Gtk.MenuItem(_("Mayan"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_O_cb, MAYAN)
menu_items.show()
- menu_items = gtk.MenuItem(_("Quipu"))
+ menu_items = Gtk.MenuItem(_("Quipu"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_O_cb, INCAN)
menu_items.show()
- menu_items = gtk.MenuItem(_("Hash"))
+ menu_items = Gtk.MenuItem(_("Hash"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_C_cb, HASH)
menu_items.show()
- menu_items = gtk.MenuItem(_("Dice"))
+ menu_items = Gtk.MenuItem(_("Dice"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_C_cb, DICE)
menu_items.show()
- menu_items = gtk.MenuItem(_("Dots"))
+ menu_items = Gtk.MenuItem(_("Dots"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_C_cb, DOTS)
menu_items.show()
- menu_items = gtk.MenuItem(_("Star"))
+ menu_items = Gtk.MenuItem(_("Star"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_C_cb, STAR)
menu_items.show()
- menu_items = gtk.MenuItem(_("Lines"))
+ menu_items = Gtk.MenuItem(_("Lines"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_C_cb, LINES)
menu_items.show()
- num_menu = gtk.MenuItem("Numbers")
+ num_menu = Gtk.MenuItem("Numbers")
num_menu.show()
num_menu.set_submenu(menu3)
# A vbox to put a menu and the canvas in:
- vbox = gtk.VBox(False, 0)
+ vbox = Gtk.VBox(False, 0)
self.win.add(vbox)
vbox.show()
- menu_bar = gtk.MenuBar()
+ menu_bar = Gtk.MenuBar()
vbox.pack_start(menu_bar, False, False, 2)
menu_bar.show()
- canvas = gtk.DrawingArea()
- vbox.pack_end(canvas, True, True)
+ canvas = Gtk.DrawingArea()
+ vbox.pack_end(canvas, True, True, 0)
canvas.show()
menu_bar.append(game_menu)
@@ -229,7 +227,7 @@ class VisualMatchMain:
def main():
- gtk.main()
+ Gtk.main()
return 0