1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00

* scalable cards (req: PIL >= 1.1.7)

git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@263 efabe8c0-fbe8-4139-b769-b5e6d273206e
This commit is contained in:
skomoroh 2011-03-06 06:33:38 +00:00
parent fd50923635
commit 24c0b00c0d
36 changed files with 857 additions and 304 deletions

View file

@ -22,3 +22,10 @@ Matthew Hohlfeld <hohlfeld@cs.ucsd.edu>
Nicola Larosa Nicola Larosa
John Stoneham <obijohn99@aol.com> John Stoneham <obijohn99@aol.com>
David Svoboda <svoboda@users.sourceforge.net> David Svoboda <svoboda@users.sourceforge.net>
Translations
============
Holger Schäkel <Holger@Schaekel-row.de> (de)
Jerzy Trzeciak <artusek@wp.pl> (pl)

View file

@ -31,6 +31,7 @@ from mfxutil import destruct, Struct
from mfxutil import pickle, unpickle, UnpicklingError from mfxutil import pickle, unpickle, UnpicklingError
from mfxutil import getusername, getprefdir from mfxutil import getusername, getprefdir
from mfxutil import latin1_to_ascii, print_err from mfxutil import latin1_to_ascii, print_err
from mfxutil import USE_PIL
from util import CARDSET, IMAGE_EXTENSIONS from util import CARDSET, IMAGE_EXTENSIONS
from settings import PACKAGE, VERSION_TUPLE, WIN_SYSTEM from settings import PACKAGE, VERSION_TUPLE, WIN_SYSTEM
from resource import CSI, CardsetConfig, Cardset, CardsetManager from resource import CSI, CardsetConfig, Cardset, CardsetManager
@ -536,11 +537,10 @@ class Application:
pass pass
self.wm_save_state() self.wm_save_state()
# save game geometry # save game geometry
geom = (self.canvas.winfo_width(), self.canvas.winfo_height())
if self.opt.save_games_geometry and not self.opt.wm_maximized: if self.opt.save_games_geometry and not self.opt.wm_maximized:
w = self.canvas.winfo_width()
h = self.canvas.winfo_height()
geom = (w, h)
self.opt.games_geometry[self.game.id] = geom self.opt.games_geometry[self.game.id] = geom
self.opt.game_geometry = geom
self.freeGame() self.freeGame()
# #
if self.nextgame.id <= 0: if self.nextgame.id <= 0:
@ -1020,8 +1020,18 @@ Please select a %s type %s.
if d.status != 0 or d.button != 1: if d.status != 0 or d.button != 1:
return None return None
cs = self.cardset_manager.get(d.key) cs = self.cardset_manager.get(d.key)
if cs is None or d.key == key: changed = (self.opt.scale_x,
self.opt.scale_y,
self.opt.auto_scale,
self.opt.preserve_aspect_ratio) != d.scale_values
if cs is None:
return None return None
if d.key == key and not changed:
return None
(self.opt.scale_x,
self.opt.scale_y,
self.opt.auto_scale,
self.opt.preserve_aspect_ratio) = d.scale_values
return cs return cs

View file

@ -31,7 +31,7 @@ from cStringIO import StringIO
# PySol imports # PySol imports
from mfxutil import Pickler, Unpickler, UnpicklingError from mfxutil import Pickler, Unpickler, UnpicklingError
from mfxutil import Image, ImageTk from mfxutil import Image, ImageTk, USE_PIL
from mfxutil import destruct, Struct, SubclassResponsibility from mfxutil import destruct, Struct, SubclassResponsibility
from mfxutil import uclock, usleep from mfxutil import uclock, usleep
from mfxutil import format_time, print_err from mfxutil import format_time, print_err
@ -135,12 +135,15 @@ class Game:
remaining = [], # list of stacks in no region remaining = [], # list of stacks in no region
# #
data = [], # raw data data = [], # raw data
init_info = [], # init info (at the start)
) )
self.init_size = (0,0)
self.event_handled = False # if click event handled by Stack (???) self.event_handled = False # if click event handled by Stack (???)
self.reset() self.reset()
# main constructor # main constructor
def create(self, app): def create(self, app):
#print 'Game.create'
old_busy = self.busy old_busy = self.busy
self.__createCommon(app) self.__createCommon(app)
self.setCursor(cursor=CURSOR_WATCH) self.setCursor(cursor=CURSOR_WATCH)
@ -186,13 +189,46 @@ class Game:
##self.top.bind('<3>', self.top._sleepEvent) ##self.top.bind('<3>', self.top._sleepEvent)
# update display properties # update display properties
self.canvas.busy = True self.canvas.busy = True
self.canvas.setInitialSize(self.width, self.height) # geometry
if self.app.opt.save_games_geometry and \ if not USE_PIL and self.app.opt.save_games_geometry and \
self.id in self.app.opt.games_geometry: self.id in self.app.opt.games_geometry:
# restore game geometry # restore game geometry
w, h = self.app.opt.games_geometry[self.id] w, h = self.app.opt.games_geometry[self.id]
self.canvas.config(width=w, height=h) self.canvas.config(width=w, height=h)
self.top.wm_geometry("") # cancel user-specified geometry if USE_PIL:
if self.app.opt.auto_scale:
w, h = self.app.opt.game_geometry
self.canvas.setInitialSize(w, h, margins=False,
scrollregion=False)
## self.canvas.config(width=w, height=h)
## dx, dy = self.canvas.xmargin, self.canvas.ymargin
## self.canvas.config(scrollregion=(-dx, -dy, dx, dy))
else:
w = int(round(self.width * self.app.opt.scale_x))
h = int(round(self.height * self.app.opt.scale_y))
self.canvas.setInitialSize(w, h)
self.top.wm_geometry("") # cancel user-specified geometry
# preserve texts positions
for t in ('info', 'help', 'misc', 'score', 'base_rank'):
item = getattr(self.texts, t)
if item:
coords = self.canvas.coords(item)
setattr(self.init_texts, t, coords)
#
for item in self.texts.list:
coords = self.canvas.coords(item)
self.init_texts.list.append(coords)
# resize
self.resizeGame()
# fix coords of cards (see self.createCards)
x, y = self.s.talon.x, self.s.talon.y
for c in self.cards:
c.moveTo(x, y)
else:
# no PIL
self.canvas.setInitialSize(self.width, self.height)
self.top.wm_geometry("") # cancel user-specified geometry
# done; update view
self.top.update_idletasks() self.top.update_idletasks()
self.canvas.busy = False self.canvas.busy = False
if DEBUG >= 4: if DEBUG >= 4:
@ -200,12 +236,11 @@ class Game:
width=2, fill=None, outline='green') width=2, fill=None, outline='green')
# #
self.stats.update_time = time.time() self.stats.update_time = time.time()
self.busy = old_busy
self.showHelp() # just in case self.showHelp() # just in case
hint_class = self.getHintClass() hint_class = self.getHintClass()
if hint_class is not None: if hint_class is not None:
self.Stuck_Class = hint_class(self, 0) self.Stuck_Class = hint_class(self, 0)
##self.reallocateStacks() self.busy = old_busy
def _checkGame(self): def _checkGame(self):
@ -262,7 +297,8 @@ class Game:
bind(self.canvas, "<2>", self.dropHandler) bind(self.canvas, "<2>", self.dropHandler)
bind(self.canvas, "<3>", self.redoHandler) bind(self.canvas, "<3>", self.redoHandler)
bind(self.canvas, '<Unmap>', self._unmapHandler) bind(self.canvas, '<Unmap>', self._unmapHandler)
bind(self.canvas, '<Configure>', self.configureHandler, add=True) bind(self.canvas, '<Configure>', self._configureHandler, add=True)
def __createCommon(self, app): def __createCommon(self, app):
self.busy = 1 self.busy = 1
@ -293,6 +329,16 @@ class Game:
misc = None, # misc = None, #
score = None, # for displaying the score score = None, # for displaying the score
base_rank = None, # for displaying the base_rank base_rank = None, # for displaying the base_rank
list = [], # list of texts (if we use many text)
)
# initial position of the texts
self.init_texts = Struct(
info = None, # misc info text
help = None, # a static help text
misc = None, #
score = None, # for displaying the score
base_rank = None, # for displaying the base_rank
list = [],
) )
def createPreview(self, app): def createPreview(self, app):
@ -409,6 +455,8 @@ class Game:
# this is called from within createGame() # this is called from within createGame()
def setSize(self, w, h): def setSize(self, w, h):
self.width, self.height = int(round(w)), int(round(h)) self.width, self.height = int(round(w)), int(round(h))
dx, dy = self.canvas.xmargin, self.canvas.ymargin
self.init_size = self.width+2*dx, self.height+2*dy
def setCursor(self, cursor): def setCursor(self, cursor):
if self.canvas: if self.canvas:
@ -424,6 +472,7 @@ class Game:
# start a new name # start a new name
def newGame(self, random=None, restart=0, autoplay=1): def newGame(self, random=None, restart=0, autoplay=1):
#print 'Game.newGame'
self.finished = False self.finished = False
old_busy, self.busy = self.busy, 1 old_busy, self.busy = self.busy, 1
self.setCursor(cursor=CURSOR_WATCH) self.setCursor(cursor=CURSOR_WATCH)
@ -538,8 +587,8 @@ class Game:
self.stats.update_time = time.time() self.stats.update_time = time.time()
self.busy = old_busy self.busy = old_busy
# #
##self.configureHandler() # reallocateCards ##self._configureHandler() # reallocateCards
after(self.top, 200, self.configureHandler) # wait for canvas is mapped after(self.top, 200, self._configureHandler) # wait for canvas is mapped
# #
if TOOLKIT == 'gtk': if TOOLKIT == 'gtk':
## FIXME ## FIXME
@ -561,6 +610,7 @@ class Game:
self.busy = old_busy self.busy = old_busy
def resetGame(self): def resetGame(self):
#print 'Game.resetGame'
self.hints.list = None self.hints.list = None
self.s.talon.removeAllCards() self.s.talon.removeAllCards()
for stack in self.allstacks: for stack in self.allstacks:
@ -638,22 +688,73 @@ class Game:
self.endGame(restart=1) self.endGame(restart=1)
self.newGame(restart=1, random=self.random) self.newGame(restart=1, random=self.random)
def reallocateStacks(self): def resizeImages(self):
w0, h0 = self.width, self.height # resizing images and cards
iw = int(self.canvas.cget('width')) if self.app.opt.auto_scale:
ih = int(self.canvas.cget('height')) if self.canvas.winfo_ismapped():
vw = self.canvas.winfo_width() # apparent size of canvas
vh = self.canvas.winfo_height() vw = self.canvas.winfo_width()
if vw <= iw or vh <= ih: vh = self.canvas.winfo_height()
else:
# we have no a real size of canvas (winfo_width / winfo_reqwidth)
# so we use a saved size
vw, vh = self.app.opt.game_geometry
if not vw:
# first run of the game
return 1, 1
iw, ih = self.init_size # requested size of canvas (createGame -> setSize)
# calculate factor of resizing
xf = float(vw)/iw
yf = float(vh)/ih
if self.app.opt.preserve_aspect_ratio:
xf = yf = min(xf, yf)
else:
xf, yf = self.app.opt.scale_x, self.app.opt.scale_y
# images
self.app.images.resize(xf, yf)
# cards
for card in self.cards:
card.update(card.id, card.deck, card.suit, card.rank, self)
return xf, yf
def resizeGame(self):
#if self.busy:
# return
if not USE_PIL:
return return
xf = float(vw)/iw self.deleteStackDesc()
yf = float(vh)/ih xf, yf = self.resizeImages()
#print 'resizeGame', xf, yf
# stacks
for stack in self.allstacks: for stack in self.allstacks:
x0, y0 = stack.init_coord x0, y0 = stack.init_coord
x, y = int(x0*xf), int(y0*yf) x, y = int(round(x0*xf)), int(round(y0*yf))
if x == stack.x and y == stack.y: #if x == stack.x and y == stack.y:
continue # continue
stack.moveTo(x, y) stack.resize(xf, yf)
stack.updatePositions()
# regions
info = []
for stacks, rect in self.regions.init_info:
rect = (int(round(rect[0]*xf)), int(round(rect[1]*yf)),
int(round(rect[2]*xf)), int(round(rect[3]*yf)))
info.append((stacks, rect))
self.regions.info = tuple(info)
# texts
for t in ('info', 'help', 'misc', 'score', 'base_rank'):
init_coord = getattr(self.init_texts, t)
if init_coord:
item = getattr(self.texts, t)
x, y = int(round(init_coord[0]*xf)), int(round(init_coord[1]*yf))
self.canvas.coords(item, x, y)
for i in range(len(self.texts.list)):
init_coord = self.init_texts.list[i]
item = self.texts.list[i]
x, y = int(round(init_coord[0]*xf)), int(round(init_coord[1]*yf))
self.canvas.coords(item, x, y)
#
#self.canvas.update()
#self.canvas.update_idletasks()
def createRandom(self, random): def createRandom(self, random):
if random is None: if random is None:
@ -985,11 +1086,27 @@ class Game:
if self.app and not self.pause: if self.app and not self.pause:
self.app.menubar.mPause() self.app.menubar.mPause()
def configureHandler(self, event=None): _resizeHandlerID = None
def _resizeHandler(self):
#print '_resizeHandler'
self._resizeHandlerID = None
self.resizeGame()
def _configureHandler(self, event=None):
#print 'configureHandler'
if not USE_PIL:
return
if not self.app:
return
if not self.canvas: if not self.canvas:
return return
for stack in self.allstacks: if not self.app.opt.auto_scale:
stack.updatePositions() return
if self.preview:
return
if self._resizeHandlerID:
self.canvas.after_cancel(self._resizeHandlerID)
self._resizeHandlerID = self.canvas.after(250, self._resizeHandler)
# #
# sound support # sound support
@ -1504,13 +1621,20 @@ class Game:
assert len(stacks) > 0 assert len(stacks) > 0
assert len(rect) == 4 and rect[0] < rect[2] and rect[1] < rect[3] assert len(rect) == 4 and rect[0] < rect[2] and rect[1] < rect[3]
if DEBUG >= 2: if DEBUG >= 2:
MfxCanvasRectangle(self.canvas, rect[0], rect[1], rect[2], rect[3], xf, yf = self.app.images._xfactor, self.app.images._yfactor
MfxCanvasRectangle(self.canvas,
xf*rect[0], yf*rect[1], xf*rect[2], yf*rect[3],
width=2, fill=None, outline='red') width=2, fill=None, outline='red')
for s in stacks: for s in stacks:
assert s and s in self.allstacks assert s and s in self.allstacks
# verify that the stack lies within the rectangle # verify that the stack lies within the rectangle
x, y, r = s.x, s.y, rect r = rect
##print x, y, r if USE_PIL:
x, y = s.init_coord
#print 'setRegion:', x, y, r
else:
x, y = s.x, s.y
#print 'setRegion:', x, y, r
assert r[0] <= x <= r[2] and r[1] <= y <= r[3] assert r[0] <= x <= r[2] and r[1] <= y <= r[3]
# verify that the stack is not already in another region # verify that the stack is not already in another region
# with the same priority # with the same priority
@ -1538,7 +1662,7 @@ class Game:
while stack in remaining: while stack in remaining:
remaining.remove(stack) remaining.remove(stack)
self.regions.remaining = tuple(remaining) self.regions.remaining = tuple(remaining)
##print self.regions.info self.regions.init_info = self.regions.info
def getInvisibleCoords(self): def getInvisibleCoords(self):
# for InvisibleStack, etc # for InvisibleStack, etc
@ -1917,6 +2041,7 @@ Congratulations, you did it !
if self.pause: if self.pause:
return 0 return 0
self.stopWinAnimation() self.stopWinAnimation()
cw, ch = self.app.images.getSize()
items = [] items = []
for s, c1, c2, color in info: for s, c1, c2, color in info:
assert c1 in s.cards and c2 in s.cards assert c1 in s.cards and c2 in s.cards
@ -1943,33 +2068,33 @@ Congratulations, you did it !
x2, y2 = s.getPositionFor(c2) x2, y2 = s.getPositionFor(c2)
if sx0 != 0 and sy0 == 0: if sx0 != 0 and sy0 == 0:
# horizontal stack # horizontal stack
y2 = y2 + self.app.images.CARDH y2 += ch
if c2 is s.cards[-1]: # top card if c2 is s.cards[-1]: # top card
x2 = x2 + self.app.images.CARDW x2 += cw
else: else:
if sx0 > 0: if sx0 > 0:
# left to right # left to right
x2 = x2 + sx0 x2 += sx0
else: else:
# right to left # right to left
x1 = x1 + self.app.images.CARDW x1 += cw
x2 = x2 + self.app.images.CARDW + sx0 x2 += cw + sx0
elif sx0 == 0 and sy0 != 0: elif sx0 == 0 and sy0 != 0:
# vertical stack # vertical stack
x2 = x2 + self.app.images.CARDW x2 += cw
if c2 is s.cards[-1]: # top card if c2 is s.cards[-1]: # top card
y2 = y2 + self.app.images.CARDH y2 += ch
else: else:
if sy0 > 0: if sy0 > 0:
# up to down # up to down
y2 = y2 + sy0 y2 = y2 + sy0
else: else:
# down to up # down to up
y1 = y1 + self.app.images.CARDH y1 += ch
y2 = y2 + self.app.images.CARDH + sy0 y2 += ch + sy0
else: else:
x2 = x2 + self.app.images.CARDW x2 += cw
y2 = y2 + self.app.images.CARDH y2 += ch
tkraise = True tkraise = True
##print c1, c2, x1, y1, x2, y2 ##print c1, c2, x1, y1, x2, y2
x1, x2 = x1-delta[0], x2+delta[1] x1, x2 = x1-delta[0], x2+delta[1]
@ -2237,19 +2362,21 @@ Congratulations, you did it !
images = self.app.images images = self.app.images
x1, y1 = from_stack.getPositionFor(from_stack.cards[-ncards]) x1, y1 = from_stack.getPositionFor(from_stack.cards[-ncards])
x2, y2 = to_stack.getPositionFor(to_stack.getCard()) x2, y2 = to_stack.getPositionFor(to_stack.getCard())
x1, y1 = x1 + images.CARD_DX, y1 + images.CARD_DY cw, ch = images.getSize()
x2, y2 = x2 + images.CARD_DX, y2 + images.CARD_DY dx, dy = images.getDelta()
x1, y1 = x1 + dx, y1 + dy
x2, y2 = x2 + dx, y2 + dy
if ncards == 1: if ncards == 1:
x1 = x1 + images.CARDW / 2 x1 += cw / 2
y1 = y1 + images.CARDH / 2 y1 += ch / 2
elif from_stack.CARD_XOFFSET[0]: elif from_stack.CARD_XOFFSET[0]:
x1 = x1 + from_stack.CARD_XOFFSET[0] / 2 x1 += from_stack.CARD_XOFFSET[0] / 2
y1 = y1 + images.CARDH / 2 y1 += ch / 2
else: else:
x1 = x1 + images.CARDW / 2 x1 += cw / 2
y1 = y1 + from_stack.CARD_YOFFSET[0] / 2 y1 += from_stack.CARD_YOFFSET[0] / 2
x2 = x2 + images.CARDW / 2 x2 += cw / 2
y2 = y2 + images.CARDH / 2 y2 += ch / 2
# draw the hint # draw the hint
arrow = MfxCanvasLine(self.canvas, x1, y1, x2, y2, width=7, arrow = MfxCanvasLine(self.canvas, x1, y1, x2, y2, width=7,
fill=self.app.opt.colors['hintarrow'], fill=self.app.opt.colors['hintarrow'],

View file

@ -32,7 +32,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
from numerica import Numerica_Hint from numerica import Numerica_Hint

View file

@ -34,7 +34,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
# ************************************************************************ # ************************************************************************

View file

@ -33,7 +33,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
from fortythieves import FortyThieves_Hint from fortythieves import FortyThieves_Hint
from spider import Spider_Hint from spider import Spider_Hint

View file

@ -32,7 +32,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
from gypsy import DieRussische_Foundation from gypsy import DieRussische_Foundation

View file

@ -34,7 +34,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
# ************************************************************************ # ************************************************************************

View file

@ -35,7 +35,6 @@ from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.hint import KlondikeType_Hint, YukonType_Hint from pysollib.hint import KlondikeType_Hint, YukonType_Hint
from pysollib.pysoltk import MfxCanvasText
from spider import Spider_SS_Foundation, Spider_RowStack, Spider_Hint from spider import Spider_SS_Foundation, Spider_RowStack, Spider_Hint

View file

@ -35,7 +35,6 @@ from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.hint import KlondikeType_Hint from pysollib.hint import KlondikeType_Hint
from pysollib.pysoltk import MfxCanvasText
from spider import Spider_RowStack, Spider_SS_Foundation, Spider_Hint from spider import Spider_RowStack, Spider_SS_Foundation, Spider_Hint

View file

@ -32,7 +32,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
# ************************************************************************ # ************************************************************************

View file

@ -276,7 +276,7 @@ class Mahjongg_RowStack(OpenStack):
drag.shade_img.delete() drag.shade_img.delete()
#game.canvas.delete(drag.shade_img) #game.canvas.delete(drag.shade_img)
drag.shade_img = None drag.shade_img = None
img = game.app.images.getShadowCard(card.deck, card.suit, card.rank) img = game.app.images.getHighlightedCard(card.deck, card.suit, card.rank)
if img is None: if img is None:
return 1 return 1
img = MfxCanvasImage(game.canvas, self.x, self.y, image=img, img = MfxCanvasImage(game.canvas, self.x, self.y, image=img,
@ -896,7 +896,7 @@ a solvable configuration.'''),
assert c1 in s.cards assert c1 in s.cards
tkraise = False tkraise = False
x, y = s.x, s.y x, y = s.x, s.y
img = self.app.images.getHighlightCard(c1.deck, c1.suit, c1.rank) img = self.app.images.getHighlightedCard(c1.deck, c1.suit, c1.rank, 'black')
if img is None: if img is None:
continue continue
img = MfxCanvasImage(self.canvas, x, y, image=img, img = MfxCanvasImage(self.canvas, x, y, image=img,

View file

@ -123,7 +123,7 @@ r(5078, "Squaring", layout="0caaacaceaciaakacmacqaasacuacyaaAacCaaacaecaicdkcamc
r(5079, "Stairs", layout="0aoaaebaybeacdccagcaicakcbmccocbqcascaucawcdAceCcaedayddaeaieaoeauedCebefbyfaagaigaogaugaCgbchcehbghakhbmhbqhashbwhcyhbAhaaiaiiaoiauiaCibejbyjdakaikaokaukdCkaelayleamdcmagmaimakmbmmcombqmasmaumawmdAmeCmaenaynaoohechychofhahkohhChhojhemhym") r(5079, "Stairs", layout="0aoaaebaybeacdccagcaicakcbmccocbqcascaucawcdAceCcaedayddaeaieaoeauedCebefbyfaagaigaogaugaCgbchcehbghakhbmhbqhashbwhcyhbAhaaiaiiaoiauiaCibejbyjdakaikaokaukdCkaelayleamdcmagmaimakmbmmcombqmasmaumawmdAmeCmaenaynaoohechychofhahkohhChhojhemhym")
r(5080, "Star Ship", layout="0eoaaabdmbdqbaCbaccckccscaAcaadbidbudaCdbceagecoeawebAeaafaefamfaqfayfaCfecgaggaigbkgdogbsgaugawgeAgaahaehamhaqhayhaChbciagicoiawibAiaajbijbujaCjackckkcskaAkaaldmldqlaCleomhachCchaehCehaghegimgiqghyghCghaihCihakhCkoadoCdoafoCfoahoChoajoCjvaevCevagvCgvaivCiCafCCfCahCCh") r(5080, "Star Ship", layout="0eoaaabdmbdqbaCbaccckccscaAcaadbidbudaCdbceagecoeawebAeaafaefamfaqfayfaCfecgaggaigbkgdogbsgaugawgeAgaahaehamhaqhayhaChbciagicoiawibAiaajbijbujaCjackckkcskaAkaaldmldqlaCleomhachCchaehCehaghegimgiqghyghCghaihCihakhCkoadoCdoafoCfoahoChoajoCjvaevCevagvCgvaivCiCafCCfCahCCh")
# #
r(5081, "Step Pyramid", layout="0aaaacaaeaagaaiaakaamaaoaaqaaacaccaecagcaicakcamcaocaqcaaeaceaoeaqeaagacgaogaqgaaiaciaoiaqiaakackaekagkaikakkamkaokaqkaamacmaemagmaimakmammaomaqmhbbhdbhfbhhbhjbhlbhnbhpbhbdhddhfdhhdhjdhldhndhpdhbfhdfhnfhpfhbhhdhhnhhphhbjhdjhfjhhjhjjhljhnjhpjhblhdlhflhhlhjlhllhnlhplpccoecogcoicokcomcpococepeepgepiepkepmeooeocgpegpmgoogocipeipgipiipkipmiooipckoekogkoikokkomkpokCffChfCjfClfCfhChhCjhClh") r(5081, "Steps Pyramid", layout="0aaaacaaeaagaaiaakaamaaoaaqaaacaccaecagcaicakcamcaocaqcaaeaceaoeaqeaagacgaogaqgaaiaciaoiaqiaakackaekagkaikakkamkaokaqkaamacmaemagmaimakmammaomaqmhbbhdbhfbhhbhjbhlbhnbhpbhbdhddhfdhhdhjdhldhndhpdhbfhdfhnfhpfhbhhdhhnhhphhbjhdjhfjhhjhjjhljhnjhpjhblhdlhflhhlhjlhllhnlhplpccoecogcoicokcomcpococepeepgepiepkepmeooeocgpegpmgoogocipeipgipiipkipmiooipckoekogkoikokkomkpokCffChfCjfClfCfhChhCjhClh")
r(5082, "Stonehenge", layout="0cdachackacoacracvacyacCacaccFcajeaneareavecagcFgddhdhhdlhdphdthdxhdBhcajcFjajkankarkavkcancFncdpchpckpcopcrpcvpcypcCpveavgavlavnavsavuavzavBavadvFdvafvFfvakvFkvamvFmvepvgpvlpvnpvspvupvzpvBpCehCghCihCkhCmhCohCqhCshCuhCwhCyhCAh") r(5082, "Stonehenge", layout="0cdachackacoacracvacyacCacaccFcajeaneareavecagcFgddhdhhdlhdphdthdxhdBhcajcFjajkankarkavkcancFncdpchpckpcopcrpcvpcypcCpveavgavlavnavsavuavzavBavadvFdvafvFfvakvFkvamvFmvepvgpvlpvnpvspvupvzpvBpCehCghCihCkhCmhCohCqhCshCuhCwhCyhCAh")
r(5083, "SunMoon", layout="0dgaciabkaamabyadebbrbbBbdccbvccaddcecheckecnebDecafbtfbAfdcgdjgdlgbxgcahchhcnhdcidjidlibribDicajbvjdckchkckkcnkbAkcalbsldcmbxmdenbBndgociobkoamobuovaevagvaivakCkh") r(5083, "SunMoon", layout="0dgaciabkaamabyadebbrbbBbdccbvccaddcecheckecnebDecafbtfbAfdcgdjgdlgbxgcahchhcnhdcidjidlibribDicajbvjdckchkckkcnkbAkcalbsldcmbxmdenbBndgociobkoamobuovaevagvaivakCkh")
r(5084, "Temple", layout="0baaacaaeaalaanaapaaraataaAaaCabEaaacaccalcbncbpcbrcatcaCcaEcajdavdaaeblebnebpebrebteaEeaffahfajfavfaxfazfblgbngbpgbrgbtgadhafhahhajhavhaxhazhaBhblibnibpibribtiafjahjajjavjaxjazjaakblkbnkbpkbrkbtkaEkajlavlaamacmalmbnmbpmbrmatmaCmaEmbaoacoaeoaloanoapoaroatoaAoaCobEohhghjghvghxghhihjihvihxiooeoqeokgomgoogoqgosgougokiomiooioqiosiouiookoqkvpgvpi") r(5084, "Temple", layout="0baaacaaeaalaanaapaaraataaAaaCabEaaacaccalcbncbpcbrcatcaCcaEcajdavdaaeblebnebpebrebteaEeaffahfajfavfaxfazfblgbngbpgbrgbtgadhafhahhajhavhaxhazhaBhblibnibpibribtiafjahjajjavjaxjazjaakblkbnkbpkbrkbtkaEkajlavlaamacmalmbnmbpmbrmatmaCmaEmbaoacoaeoaloanoapoaroatoaAoaCobEohhghjghvghxghhihjihvihxiooeoqeokgomgoogoqgosgougokiomiooioqiosiouiookoqkvpgvpi")

View file

@ -250,33 +250,31 @@ class Shisen_RowStack(Mahjongg_RowStack):
def drawArrow(self, other_stack, sleep): def drawArrow(self, other_stack, sleep):
game = self.game game = self.game
images = game.app.images
cs = game.app.cardset
path = self.acceptsCards(other_stack, [other_stack.cards[-1]]) path = self.acceptsCards(other_stack, [other_stack.cards[-1]])
#print path #print path
x0, y0 = game.XMARGIN, game.YMARGIN x0, y0 = game.XMARGIN, game.YMARGIN
#print x0, y0 cardw, cardh = images.CARDW, images.CARDH
images = game.app.images
cs = game.app.cardset
if cs.version >= 6: if cs.version >= 6:
cardw = images.CARDW-cs.SHADOW_XOFFSET cardw -= cs.SHADOW_XOFFSET
cardh = images.CARDH-cs.SHADOW_YOFFSET cardh -= cs.SHADOW_YOFFSET
else:
cardw = images.CARDW
cardh = images.CARDH
coords = [] coords = []
dx, dy = game._delta_x, game._delta_y dx, dy = game._delta_x, game._delta_y
xf, yf = images._xfactor, images._yfactor
for x, y in path: for x, y in path:
if x == 0: if x == 0:
coords.append(6) coords.append(6)
elif x == game.L[0]+1: elif x == game.L[0]+1:
coords.append(x0+cardw*(x-1)+10+dx) coords.append(int(round(xf * (x0+cardw*(x-1)+10+dx))))
else: else:
coords.append(x0+cardw/2+cardw*(x-1)+dx) coords.append(int(round(xf * (x0+cardw/2+cardw*(x-1)+dx))))
if y == 0: if y == 0:
coords.append(6) coords.append(6)
elif y == game.L[1]+1: elif y == game.L[1]+1:
coords.append(y0+cardh*(y-1)+6) coords.append(int(round(yf * (y0+cardh*(y-1)+6))))
else: else:
coords.append(y0+cardh/2+cardh*(y-1)) coords.append(int(round(yf * (y0+cardh/2+cardh*(y-1)))))
#print coords #print coords
##s1 = min(cardw/2, cardh/2, 30) ##s1 = min(cardw/2, cardh/2, 30)
##w = min(s1/3, 7) ##w = min(s1/3, 7)

View file

@ -33,7 +33,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
# ************************************************************************ # ************************************************************************

View file

@ -64,7 +64,7 @@ class PushPin_Talon(DealRowTalonStack):
if not r.cards: if not r.cards:
return self.dealRowAvail(rows=[r], sound=sound) return self.dealRowAvail(rows=[r], sound=sound)
return self.dealRowAvail(rows=[self.game.s.rows[0]], sound=sound) return self.dealRowAvail(rows=[self.game.s.rows[0]], sound=sound)
getBottomImage = Stack._getBlankBottomImage getBottomImage = Stack._getNoneBottomImage
class PushPin_RowStack(ReserveStack): class PushPin_RowStack(ReserveStack):

View file

@ -33,7 +33,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
from unionsquare import UnionSquare_Foundation from unionsquare import UnionSquare_Foundation

View file

@ -81,6 +81,7 @@ Straight
Three of a Kind Three of a Kind
Two Pair Two Pair
One Pair''')) One Pair'''))
self.texts.list.append(t)
bb = t.bbox() bb = t.bbox()
x = bb[1][0] + 16 x = bb[1][0] + 16
h = bb[1][1] - bb[0][1] h = bb[1][1] - bb[0][1]
@ -91,6 +92,7 @@ One Pair'''))
t = MfxCanvasText(self.canvas, x, y, anchor="nw", t = MfxCanvasText(self.canvas, x, y, anchor="nw",
font=self.app.getFont("canvas_default"), font=self.app.getFont("canvas_default"),
text="100\n75\n50\n25\n20\n15\n10\n5\n2") text="100\n75\n50\n25\n20\n15\n10\n5\n2")
self.texts.list.append(t)
x = t.bbox()[1][0] + 16 x = t.bbox()[1][0] + 16
self.texts.misc = MfxCanvasText(self.canvas, x, y, anchor="nw", self.texts.misc = MfxCanvasText(self.canvas, x, y, anchor="nw",
font=self.app.getFont("canvas_default"), font=self.app.getFont("canvas_default"),
@ -113,18 +115,17 @@ One Pair'''))
# create texts 2) # create texts 2)
if self.preview <= 1: if self.preview <= 1:
self.texts.addattr(hands=[])
for i in (4, 9, 14, 19, 24): for i in (4, 9, 14, 19, 24):
tx, ty, ta, tf = l.getTextAttr(s.rows[i], anchor="e") tx, ty, ta, tf = l.getTextAttr(s.rows[i], anchor="e")
t = MfxCanvasText(self.canvas, tx+8, ty, t = MfxCanvasText(self.canvas, tx+8, ty,
anchor=ta, anchor=ta,
font=self.app.getFont("canvas_default")) font=self.app.getFont("canvas_default"))
self.texts.hands.append(t) self.texts.list.append(t)
for i in range(20, 25): for i in range(20, 25):
tx, ty, ta, tf = l.getTextAttr(s.rows[i], anchor="ss") tx, ty, ta, tf = l.getTextAttr(s.rows[i], anchor="ss")
t = MfxCanvasText(self.canvas, tx, ty, anchor=ta, t = MfxCanvasText(self.canvas, tx, ty, anchor=ta,
font=self.app.getFont("canvas_default")) font=self.app.getFont("canvas_default"))
self.texts.hands.append(t) self.texts.list.append(t)
self.texts.score = MfxCanvasText(self.canvas, l.XM, 5*l.YS, anchor="sw", self.texts.score = MfxCanvasText(self.canvas, l.XM, 5*l.YS, anchor="sw",
font=self.app.getFont("canvas_large")) font=self.app.getFont("canvas_large"))
@ -171,7 +172,7 @@ One Pair'''))
type, value = self.getHandScore(self.poker_hands[i]) type, value = self.getHandScore(self.poker_hands[i])
if 0 <= type <= 8: if 0 <= type <= 8:
count[type] = count[type] + 1 count[type] = count[type] + 1
self.texts.hands[i].config(text=str(value)) self.texts.list[i+2].config(text=str(value))
score = score + value score = score + value
t = '\n'.join(map(str, count)) t = '\n'.join(map(str, count))
self.texts.misc.config(text=t) self.texts.misc.config(text=t)

View file

@ -34,7 +34,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
# ************************************************************************ # ************************************************************************

View file

@ -34,7 +34,7 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
# ************************************************************************ # ************************************************************************
# * Sultan # * Sultan

View file

@ -34,7 +34,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
# ************************************************************************ # ************************************************************************

View file

@ -64,10 +64,12 @@ class FlowerClock(AbstractFlowerGame):
for i in range(12): for i in range(12):
x0 = x + xoffset[i] * l.XS x0 = x + xoffset[i] * l.XS
y0 = y + yoffset[i] * l.YS y0 = y + yoffset[i] * l.YS
s.foundations.append(FlowerClock_Foundation(x0, y0, self, ANY_SUIT, base_rank=3)) stack = FlowerClock_Foundation(x0, y0, self, ANY_SUIT, base_rank=3)
s.foundations.append(stack)
t = MfxCanvasText(self.canvas, x0 + l.CW / 2, y0 + l.YS, t = MfxCanvasText(self.canvas, x0 + l.CW / 2, y0 + l.YS,
anchor="center", font=font, anchor="center", font=font,
text=self.SUITS[i]) text=self.SUITS[i])
stack.texts.misc = t
# Create row stacks # Create row stacks
for j in range(2): for j in range(2):
@ -311,15 +313,15 @@ class Pagoda(AbstractFlowerGame):
self.setSize(l.XM + l.XS * 11, l.YS * 6) self.setSize(l.XM + l.XS * 11, l.YS * 6)
# Create foundations # Create foundations
self.foundation_texts = []
id = 0 id = 0
for j in range(4): for j in range(4):
x, y = l.XM + l.XS * 8, l.YM * 3 + l.YS * j * 1.5 x, y = l.XM + l.XS * 8, l.YM * 3 + l.YS * j * 1.5
for i in range(3): for i in range(3):
s.foundations.append(Pagoda_Foundation(x, y, self, id)) stack = Pagoda_Foundation(x, y, self, id)
s.foundations.append(stack)
t = MfxCanvasText(self.canvas, x + l.CW / 2, y - 12, t = MfxCanvasText(self.canvas, x + l.CW / 2, y - 12,
anchor="center", font=font) anchor="center", font=font)
self.foundation_texts.append(t) stack.texts.misc = t
x = x + l.XS x = x + l.XS
id = id + 1 id = id + 1
@ -370,7 +372,7 @@ class Pagoda(AbstractFlowerGame):
text = _("Rising") text = _("Rising")
else: else:
text = _("Setting") text = _("Setting")
self.foundation_texts[i].config(text=text) s.texts.misc.config(text=text)
# #
# Game over rides # Game over rides
@ -468,13 +470,14 @@ class GreatWall(AbstractFlowerGame):
self.setSize(w, h) self.setSize(w, h)
# Create foundations # Create foundations
self.foundation_texts = []
x, y = (l.XM, l.XM, w - l.XS, w - l.XS), (l.YM, h / 2, l.YM, h / 2) x, y = (l.XM, l.XM, w - l.XS, w - l.XS), (l.YM, h / 2, l.YM, h / 2)
for i in range(4): for i in range(4):
s.foundations.append(GreatWall_FoundationStack(x[i], y[i] + l.YM, self, -1, base_rank=i)) stack = GreatWall_FoundationStack(x[i], y[i] + l.YM, self, -1,
self.foundation_texts.append(MfxCanvasText(self.canvas, base_rank=i)
x[i] + l.CW / 2, y[i], s.foundations.append(stack)
anchor="center", font=font)) stack.texts.misc = MfxCanvasText(self.canvas,
x[i] + l.CW / 2, y[i],
anchor="center", font=font)
# Create row stacks # Create row stacks
x = l.XM + l.XS * 1.5 x = l.XM + l.XS * 1.5
@ -501,14 +504,15 @@ class GreatWall(AbstractFlowerGame):
if self.preview > 1: if self.preview > 1:
return return
for i in range(4): for i in range(4):
l = len(self.s.foundations[i].cards) / 12 stack = self.s.foundations[i]
l = len(stack.cards) / 12
if l == 0: if l == 0:
t = "" text = ""
elif l == 4: elif l == 4:
t = _("Filled") text = _("Filled")
else: else:
t = str(l) + (_("st"), _("nd"), _("rd"), _("th"))[l - 1] + _(" Deck") text = str(l) + (_("st"), _("nd"), _("rd"), _("th"))[l - 1] + _(" Deck")
self.foundation_texts[i].config(text=str(t)) stack.texts.misc.config(text=text)
# #
# Game over rides # Game over rides
@ -568,11 +572,13 @@ class FourWinds(AbstractFlowerGame):
for i in range(4): for i in range(4):
x0 = x + (xoffset[i] * l.XS) x0 = x + (xoffset[i] * l.XS)
y0 = y + (yoffset[i] * l.YS) y0 = y + (yoffset[i] * l.YS)
s.foundations.append(FourWinds_Foundation(x0, y0, self, -1, stack = FourWinds_Foundation(x0, y0, self, -1,
max_cards=12, max_accept=1, base_rank=i)) max_cards=12, max_accept=1, base_rank=i)
s.foundations.append(stack)
t = MfxCanvasText(self.canvas, x0 + l.CW / 2, y0 + l.YS + 5, t = MfxCanvasText(self.canvas, x0 + l.CW / 2, y0 + l.YS + 5,
anchor="center", font=font, anchor="center", font=font,
text=TEXTS[i]) text=TEXTS[i])
stack.texts.misc = t
# Create rows # Create rows
xoffset = (1.25, 3.75, 3.75, 1.25) xoffset = (1.25, 3.75, 3.75, 1.25)
@ -580,11 +586,14 @@ class FourWinds(AbstractFlowerGame):
for i in range(4): for i in range(4):
x0 = x + (xoffset[i] * l.XS) x0 = x + (xoffset[i] * l.XS)
y0 = y + (yoffset[i] * l.YS) y0 = y + (yoffset[i] * l.YS)
s.rows.append(FourWinds_RowStack(x0, y0, self, yoffset=10, stack = FourWinds_RowStack(x0, y0, self, yoffset=10,
max_cards=3, max_accept=1, base_rank=ANY_RANK)) max_cards=3, max_accept=1,
base_rank=ANY_RANK)
s.rows.append(stack)
t = MfxCanvasText(self.canvas, x0 + l.CW / 2, y0 + l.YS + 5, t = MfxCanvasText(self.canvas, x0 + l.CW / 2, y0 + l.YS + 5,
anchor="center", font=font, anchor="center", font=font,
text=TEXTS[i+4]) text=TEXTS[i+4])
stack.texts.misc = t
self.setRegion(s.rows, (x + l.XS, y + l.YS * 0.65, x + l.XS * 4 + 5, y + l.YS * 3 + 5)) self.setRegion(s.rows, (x + l.XS, y + l.YS * 0.65, x + l.XS * 4 + 5, y + l.YS * 3 + 5))
# Create talon # Create talon

View file

@ -297,10 +297,12 @@ class BitsNBytes(Game):
for j in range(4): for j in range(4):
x = l.XM * 4 + l.XS * 7 x = l.XM * 4 + l.XS * 7
for i in range(4): for i in range(4):
s.rows.append(Bits_RowStack(x, y, self, max_cards=1, stack = Bits_RowStack(x, y, self, max_cards=1, max_accept=1,
max_accept=1, base_suit=j, max_move=0)) base_suit=j, max_move=0)
self.bit_texts.append(MfxCanvasText(self.canvas, x + l.CW / 2 , y + l.CH / 2, s.rows.append(stack)
anchor="center", font=font)) stack.texts.misc = MfxCanvasText(self.canvas,
x + l.CW / 2 , y + l.CH / 2,
anchor="center", font=font)
x = x - l.XS x = x - l.XS
y = y + l.YS y = y + l.YS
@ -347,7 +349,8 @@ class BitsNBytes(Game):
break break
s = self.s.foundations[j].cards[-1].rank + 1 s = self.s.foundations[j].cards[-1].rank + 1
for i in range(4): for i in range(4):
self.bit_texts[i + j * 4].config(text = str(s % 2)) stack = self.s.rows[i + j * 4]
stack.texts.misc.config(text = str(s % 2))
s = int(s / 2) s = int(s / 2)
def _shuffleHook(self, cards): def _shuffleHook(self, cards):

View file

@ -34,8 +34,6 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
# ************************************************************************ # ************************************************************************

View file

@ -29,10 +29,10 @@ import traceback
# PySol imports # PySol imports
from resource import CSI from resource import CSI
from settings import TOOLKIT from settings import TOOLKIT
from mfxutil import Image, ImageTk from mfxutil import Image, ImageTk, USE_PIL
# Toolkit imports # Toolkit imports
from pysoltk import loadImage, copyImage, createImage, shadowImage, createBottom from pysoltk import loadImage, copyImage, createImage, shadowImage, createBottom, resizeBottom
# ************************************************************************ # ************************************************************************
@ -54,37 +54,26 @@ class Images:
self.d = dataloader self.d = dataloader
self.cs = cs self.cs = cs
self.reduced = r self.reduced = r
self._xfactor = 1.0
self._yfactor = 1.0
if cs is None: if cs is None:
return return
self.use_pil = False self._setSize()
if TOOLKIT == 'tk' and Image and Image.VERSION >= '1.1.7':
self.use_pil = True
# copy from cardset
self.CARDW, self.CARDH, self.CARDD = cs.CARDW/r, cs.CARDH/r, cs.CARDD/r
self.CARD_XOFFSET = cs.CARD_XOFFSET
self.CARD_YOFFSET = cs.CARD_YOFFSET
if r > 1:
self.CARD_XOFFSET = max(10, cs.CARD_XOFFSET)/r
self.CARD_YOFFSET = max(10, cs.CARD_YOFFSET)/r
self.SHADOW_XOFFSET, self.SHADOW_YOFFSET = cs.SHADOW_XOFFSET/r, cs.SHADOW_YOFFSET/r
self.CARD_DX, self.CARD_DY = cs.CARD_DX/r, cs.CARD_DY/r
# other
self._shade_index = 0
self._card = [] self._card = []
self._back = [] self._back = []
self._bottom = [] self._bottom = [] # bottom of stack (link to _bottom_negative/_bottom_positive)
self._bottom_negative = [] self._bottom_negative = [] # negative bottom of stack (white)
self._bottom_positive = [] self._bottom_positive = [] # positive bottom of stack (black)
self._blank_bottom = None self._blank_bottom = None # blank (transparent) bottom of stack
self._letter = [] self._letter = [] # images of letter
self._letter_negative = [] self._letter_negative = []
self._letter_positive = [] self._letter_positive = []
self._shadow = [] self._shadow = [] # vertical shadow of card (used when we drag a card)
self._xshadow = [] self._xshadow = [] # horizontal shadow of card
self._shade = []
self._shadow_cards = {} # key: (suit, rank)
self._pil_shadow = {} # key: (width, height) self._pil_shadow = {} # key: (width, height)
self._pil_shadow_image = None self._highlight = [] # highlight of card (tip)
self._highlight_index = 0 #
self._highlighted_images = {} # key: (suit, rank)
def destruct(self): def destruct(self):
pass pass
@ -115,9 +104,13 @@ class Images:
imagedir = self.d.findDir(cs_type, d) imagedir = self.d.findDir(cs_type, d)
except: except:
pass pass
if not self.use_pil or imagedir is None: if not USE_PIL or imagedir is None:
# load image # load image
return self.__loadCard(filename+self.cs.ext, check_w, check_h) img = self.__loadCard(filename+self.cs.ext, check_w, check_h)
if USE_PIL:
# we have no bottom images (data/images/cards/bottoms/<cs_type>)
img = img.resize(self._xfactor, self._yfactor)
return img
# create image # create image
d = os.path.join('images', 'cards', 'bottoms', cs_type) d = os.path.join('images', 'cards', 'bottoms', cs_type)
try: try:
@ -134,9 +127,10 @@ class Images:
self._back.append(ImagesCardback(len(self._back), name, im1, im2)) self._back.append(ImagesCardback(len(self._back), name, im1, im2))
def _createMissingImages(self): def _createMissingImages(self):
cw, ch = self.getSize()
# back # back
if not self._back: if not self._back:
im = createImage(self.CARDW, self.CARDH, fill="#a0a0a0", outline="#000000") im = createImage(cw, ch, fill="#a0a0a0", outline="#000000")
name = "" name = ""
self.__addBack(im, name) self.__addBack(im, name)
self.cs.backnames = tuple(self.cs.backnames) + (name,) self.cs.backnames = tuple(self.cs.backnames) + (name,)
@ -145,21 +139,21 @@ class Images:
neg_bottom = None neg_bottom = None
while len(self._bottom_positive) < 7: while len(self._bottom_positive) < 7:
if bottom is None: if bottom is None:
bottom = createImage(self.CARDW, self.CARDH, fill=None, outline="#000000") bottom = createImage(cw, ch, fill=None, outline="#000000")
self._bottom_positive.append(bottom) self._bottom_positive.append(bottom)
while len(self._bottom_negative) < 7: while len(self._bottom_negative) < 7:
if neg_bottom is None: if neg_bottom is None:
neg_bottom = createImage(self.CARDW, self.CARDH, fill=None, outline="#ffffff") neg_bottom = createImage(cw, ch, fill=None, outline="#ffffff")
self._bottom_negative.append(neg_bottom) self._bottom_negative.append(neg_bottom)
while len(self._letter_positive) < 4: while len(self._letter_positive) < 4:
if bottom is None: if bottom is None:
bottom = createImage(self.CARDW, self.CARDH, fill=None, outline="#000000") bottom = createImage(cw, ch, fill=None, outline="#000000")
self._letter_positive.append(bottom) self._letter_positive.append(bottom)
while len(self._letter_negative) < 4: while len(self._letter_negative) < 4:
if neg_bottom is None: if neg_bottom is None:
neg_bottom = createImage(self.CARDW, self.CARDH, fill=None, outline="#ffffff") neg_bottom = createImage(cw, ch, fill=None, outline="#ffffff")
self._letter_negative.append(neg_bottom) self._letter_negative.append(neg_bottom)
self._blank_bottom = createImage(self.CARDW, self.CARDH, fill=None, outline=None) self._blank_bottom = createImage(cw, ch, fill=None, outline=None)
def load(self, app, progress=None): def load(self, app, progress=None):
ext = self.cs.ext[1:] ext = self.cs.ext[1:]
@ -199,7 +193,7 @@ class Images:
self._letter_negative.append(self.__loadBottom(name, color='white')) self._letter_negative.append(self.__loadBottom(name, color='white'))
if progress: progress.update(step=pstep) if progress: progress.update(step=pstep)
# shadow # shadow
if not self.use_pil: if not USE_PIL:
for i in range(self.cs.nshadows): for i in range(self.cs.nshadows):
name = "shadow%02d.%s" % (i, ext) name = "shadow%02d.%s" % (i, ext)
im = self.__loadCard(name, check_w=0, check_h=0) im = self.__loadCard(name, check_w=0, check_h=0)
@ -210,10 +204,10 @@ class Images:
self._xshadow.append(im) self._xshadow.append(im)
if progress: progress.update(step=pstep) if progress: progress.update(step=pstep)
# shade # shade
if self.use_pil: if USE_PIL:
self._shade.append(self._getShadow(self._card[0], None, '#3896f8')) self._highlight.append(self._getHighlight(self._card[0], None, '#3896f8'))
else: else:
self._shade.append(self.__loadCard("shade." + ext)) self._highlight.append(self.__loadCard("shade." + ext))
if progress: progress.update(step=pstep) if progress: progress.update(step=pstep)
# create missing # create missing
self._createMissingImages() self._createMissingImages()
@ -278,8 +272,9 @@ class Images:
x1, y1 = stack.getPositionFor(cards[-1]) x1, y1 = stack.getPositionFor(cards[-1])
x0, x1 = min(x1, x0), max(x1, x0) x0, x1 = min(x1, x0), max(x1, x0)
y0, y1 = min(y1, y0), max(y1, y0) y0, y1 = min(y1, y0), max(y1, y0)
x1 += self.CARDW cw, ch = self.getSize()
y1 += self.CARDH x1 += cw
y1 += ch
w, h = x1-x0, y1-y0 w, h = x1-x0, y1-y0
if (w,h) in self._pil_shadow: if (w,h) in self._pil_shadow:
return self._pil_shadow[(w,h)] return self._pil_shadow[(w,h)]
@ -298,43 +293,43 @@ class Images:
mask = mask.crop((sx,sy,w,h)) mask = mask.crop((sx,sy,w,h))
tmp = Image.new('RGBA', (w-sx,h-sy)) tmp = Image.new('RGBA', (w-sx,h-sy))
shadow.paste(tmp, (0,0), mask) shadow.paste(tmp, (0,0), mask)
#
shadow = ImageTk.PhotoImage(shadow) shadow = ImageTk.PhotoImage(shadow)
self._pil_shadow[(w,h)] = shadow self._pil_shadow[(w,h)] = shadow
return shadow return shadow
def getShade(self): def getShade(self):
return self._shade[self._shade_index] # highlight
return self._highlight[self._highlight_index]
def _getShadow(self, image, card, color='#3896f8', factor=0.3): def _getHighlight(self, image, card, color='#3896f8', factor=0.3):
if self.use_pil: if USE_PIL:
# use alpha image; one for each color # use semitransparent image; one for each color (PIL >= 1.1.7)
if color in self._shadow_cards: if color in self._highlighted_images:
shade = self._shadow_cards[color] shade = self._highlighted_images[color]
else: else:
shade = shadowImage(image, color, factor) shade = shadowImage(image, color, factor)
self._shadow_cards[color] = shade self._highlighted_images[color] = shade
else: else:
if card in self._shadow_cards: # use alpha blending (PIL <= 1.1.6)
shade = self._shadow_cards[card] if card in self._highlighted_images:
shade = self._highlighted_images[card]
else: else:
shade = shadowImage(image, color, factor) shade = shadowImage(image, color, factor)
self._shadow_cards[card] = shade self._highlighted_images[card] = shade
if not shade: if not shade:
# we have not PIL
return self.getShade() return self.getShade()
return shade return shade
def getShadowCard(self, deck, suit, rank): def getHighlightedCard(self, deck, suit, rank, color=None):
image = self.getFace(deck, suit, rank) image = self.getFace(deck, suit, rank)
return self._getShadow(image, (suit, rank)) if color:
return self._getHighlight(image, (suit, rank, color), color)
return self._getHighlight(image, (suit, rank))
def getHighlightCard(self, deck, suit, rank): def getHighlightedBack(self):
image = self.getFace(deck, suit, rank)
return self._getShadow(image, (suit, rank, 'black'), 'black')
def getShadowBack(self):
image = self.getBack() image = self.getBack()
return self._getShadow(image, 'back') return self._getHighlight(image, 'back')
def getCardbacks(self): def getCardbacks(self):
return self._back return self._back
@ -347,6 +342,83 @@ class Images:
self._bottom = self._bottom_positive self._bottom = self._bottom_positive
self._letter = self._letter_positive self._letter = self._letter_positive
def _setSize(self, xf=1, yf=1):
#print 'Images._setSize', xf, yf
self._xfactor = xf
self._yfactor = yf
cs = self.cs
if cs is None:
return
r = self.reduced
xf = float(xf)/r
yf = float(yf)/r
# copy from cardset
self.CARDW, self.CARDH = int(cs.CARDW*xf), int(cs.CARDH*yf)
if r > 1:
self.CARD_XOFFSET = max(10/r, int(cs.CARD_XOFFSET*xf))
self.CARD_YOFFSET = max(10/r, int(cs.CARD_YOFFSET*yf))
else:
self.CARD_XOFFSET = int(cs.CARD_XOFFSET*xf)
self.CARD_YOFFSET = int(cs.CARD_YOFFSET*yf)
self.SHADOW_XOFFSET = int(cs.SHADOW_XOFFSET*xf)
self.SHADOW_YOFFSET = int(cs.SHADOW_YOFFSET*yf)
self.CARD_DX, self.CARD_DY = int(cs.CARD_DX*xf), int(cs.CARD_DY*yf)
def getSize(self):
return (int(self.CARDW * self._xfactor),
int(self.CARDH * self._yfactor))
def getOffsets(self):
return (int(self.CARD_XOFFSET * self._xfactor),
int(self.CARD_YOFFSET * self._yfactor))
def getDelta(self):
return (int(self.CARD_DX * self._xfactor),
int(self.CARD_DY * self._yfactor))
def resize(self, xf, yf):
#print 'Images.resize:', xf, yf, self._card[0].width()
if self._xfactor == xf and self._yfactor == yf:
#print 'no resize'
return
self._xfactor = xf
self._yfactor = yf
# cards
cards = []
for c in self._card:
c = c.resize(xf, yf)
cards.append(c)
self._card = cards
# back
for b in self._back:
b.image = b.image.resize(xf, yf)
# stack bottom image
neg = self._bottom is self._bottom_negative
self._bottom_negative = []
self._bottom_positive = []
for i in range(self.cs.nbottoms):
name = "bottom%02d" % (i + 1)
self._bottom_positive.append(self.__loadBottom(name, color='black'))
name = "bottom%02d-n" % (i + 1)
self._bottom_negative.append(self.__loadBottom(name, color='white'))
# letters
self._letter_positive = []
self._letter_negative = []
for rank in range(self.cs.nletters):
name = "l%02d" % (rank + 1)
self._letter_positive.append(self.__loadBottom(name, color='black'))
name = "l%02d-n" % (rank + 1)
self._letter_negative.append(self.__loadBottom(name, color='white'))
self._createMissingImages()
self.setNegative(neg)
#
self._highlighted_images = {}
self._highlight = []
self._highlight.append(self._getHighlight(self._card[0], None, '#3896f8'))
self._pil_shadow = {}
def reset(self):
print 'Image.reset'
self.resize(1, 1)
# ************************************************************************ # ************************************************************************
# * # *
@ -371,9 +443,9 @@ class SubsampledImages(Images):
self._back.append(ImagesCardback(len(self._back), _back.name, im, im)) self._back.append(ImagesCardback(len(self._back), _back.name, im, im))
# #
CW, CH = self.CARDW, self.CARDH CW, CH = self.CARDW, self.CARDH
for im in images._shade: for im in images._highlight:
##self._shade.append(None) ##self._highlight.append(None)
self._shade.append(copyImage(im, 0, 0, CW, CH)) self._highlight.append(copyImage(im, 0, 0, CW, CH))
def getShadow(self, ncards): def getShadow(self, ncards):
return None return None

View file

@ -89,10 +89,8 @@ class Layout:
self.CH = images.CARDH self.CH = images.CARDH
self.XOFFSET = images.CARD_XOFFSET self.XOFFSET = images.CARD_XOFFSET
self.YOFFSET = images.CARD_YOFFSET self.YOFFSET = images.CARD_YOFFSET
self.XM = layout_x_margin # XMARGIN
self.XM = layout_x_margin # XMARGIN self.YM = layout_y_margin # YMARGIN
self.YM = layout_y_margin # YMARGIN
if card_x_space is None: if card_x_space is None:
self.XS = self.CW + layout_card_x_space # XSPACE self.XS = self.CW + layout_card_x_space # XSPACE
@ -914,8 +912,9 @@ class Layout:
w = XM * 2 + toprows * XS w = XM * 2 + toprows * XS
# set size so that at least 2/3 of a card is visible with 12 cards # set size so that at least 2/3 of a card is visible with 12 cards
h = CH * 2 / 3 + (playcards - 1) * self.YOFFSET h1 = CH * 2 / 3 + (playcards - 1) * self.YOFFSET
h = max(h, 2 * YS) h2 = (3 + reserves / decks) * YS
h = max(h1, h2)
# create foundations # create foundations
x, y = w - XS * decks, YM x, y = w - XS * decks, YM

View file

@ -36,7 +36,7 @@ try:
except: except:
thread = None thread = None
from settings import PACKAGE, TOOLKIT from settings import PACKAGE, TOOLKIT, USE_TILE
Image = ImageTk = ImageOps = None Image = ImageTk = ImageOps = None
if TOOLKIT == 'tk': if TOOLKIT == 'tk':
@ -54,7 +54,13 @@ if TOOLKIT == 'tk':
import BmpImagePlugin import BmpImagePlugin
import PpmImagePlugin import PpmImagePlugin
Image._initialized = 2 Image._initialized = 2
USE_PIL = False
if TOOLKIT == 'tk' and USE_TILE and Image and Image.VERSION >= '1.1.7':
USE_PIL = True
# debug
#Image = None
#USE_PIL = False
# ************************************************************************ # ************************************************************************
# * exceptions # * exceptions

View file

@ -95,6 +95,7 @@ randomize_place = boolean
save_cardsets = boolean save_cardsets = boolean
dragcursor = boolean dragcursor = boolean
save_games_geometry = boolean save_games_geometry = boolean
game_geometry = int_list(min=2, max=2)
sound = boolean sound = boolean
sound_mode = integer(0, 1) sound_mode = integer(0, 1)
sound_sample_volume = integer(0, 128) sound_sample_volume = integer(0, 128)
@ -166,7 +167,11 @@ highlight_piles = float(0.2, 9.9)
7 = string_list(min=2, max=2) 7 = string_list(min=2, max=2)
8 = string_list(min=2, max=2) 8 = string_list(min=2, max=2)
9 = string_list(min=2, max=2) 9 = string_list(min=2, max=2)
scale_cards = boolean
scale_x = float
scale_y = float
auto_scale = boolean
preserve_aspect_ratio = boolean
'''.splitlines() '''.splitlines()
@ -237,7 +242,6 @@ class Options:
#('favorite_gameid', 'list'), #('favorite_gameid', 'list'),
] ]
def __init__(self): def __init__(self):
self._config = None # configobj.ConfigObj instance self._config = None # configobj.ConfigObj instance
self._config_encoding = 'utf-8' self._config_encoding = 'utf-8'
@ -367,10 +371,17 @@ class Options:
self.wm_maximized = 0 self.wm_maximized = 0
self.save_games_geometry = False self.save_games_geometry = False
self.games_geometry = {} # saved games geometry (gameid: (width, height)) self.games_geometry = {} # saved games geometry (gameid: (width, height))
self.game_geometry = (0, 0) # game geometry before exit
# #
self.randomize_place = False self.randomize_place = False
self.save_cardsets = True self.save_cardsets = True
self.dragcursor = True self.dragcursor = True
#
self.scale_cards = False
self.scale_x = 1.0
self.scale_y = 1.0
self.auto_scale = False
self.preserve_aspect_ratio = True
def setDefaults(self, top=None): def setDefaults(self, top=None):
WIN_SYSTEM = settings.WIN_SYSTEM WIN_SYSTEM = settings.WIN_SYSTEM
@ -477,11 +488,15 @@ class Options:
# cardsets # cardsets
for key, val in self.cardset.items(): for key, val in self.cardset.items():
config['cardsets'][str(key)] = val config['cardsets'][str(key)] = val
for key in ('scale_cards', 'scale_x', 'scale_y',
'auto_scale', 'preserve_aspect_ratio'):
config['cardsets'][key] = getattr(self, key)
# games_geometry # games_geometry
config['games_geometry'].clear() config['games_geometry'].clear()
for key, val in self.games_geometry.items(): for key, val in self.games_geometry.items():
config['games_geometry'][str(key)] = val config['games_geometry'][str(key)] = val
config['general']['game_geometry'] = self.game_geometry
config.write() config.write()
##config.write(sys.stdout); print ##config.write(sys.stdout); print
@ -628,6 +643,14 @@ class Options:
self.cardset[int(key)] = val self.cardset[int(key)] = val
except: except:
traceback.print_exc() traceback.print_exc()
for key, t in (('scale_cards', 'bool'),
('scale_x', 'float'),
('scale_y', 'float'),
('auto_scale', 'bool'),
('preserve_aspect_ratio', 'bool')):
val = self._getOption('cardsets', key, t)
if val is not None:
setattr(self, key, val)
# games_geometry # games_geometry
for key, val in config['games_geometry'].items(): for key, val in config['games_geometry'].items():
@ -637,5 +660,11 @@ class Options:
self.games_geometry[int(key)] = val self.games_geometry[int(key)] = val
except: except:
traceback.print_exc() traceback.print_exc()
game_geometry = self._getOption('general', 'game_geometry', 'list')
if game_geometry is not None:
try:
self.game_geometry = tuple(int(i) for i in game_geometry)
except:
traceback.print_exc()

View file

@ -30,8 +30,8 @@ PACKAGE = 'PySolFC'
TITLE = 'PySol' TITLE = 'PySol'
PACKAGE_URL = 'http://pysolfc.sourceforge.net/' PACKAGE_URL = 'http://pysolfc.sourceforge.net/'
VERSION = '2.0.1' VERSION = '3.0'
VERSION_TUPLE = (2,0,1) VERSION_TUPLE = (3,0,0)
# Tk windowing system (auto set up in init.py) # Tk windowing system (auto set up in init.py)
WIN_SYSTEM = 'x11' # win32, x11, aqua, classic WIN_SYSTEM = 'x11' # win32, x11, aqua, classic

View file

@ -97,7 +97,7 @@ import types
# PySol imports # PySol imports
from mfxutil import Struct, kwdefault, SubclassResponsibility from mfxutil import Struct, kwdefault, SubclassResponsibility
from mfxutil import Image, ImageTk from mfxutil import Image, ImageTk, USE_PIL
from util import ACE, KING from util import ACE, KING
from util import ANY_SUIT, ANY_COLOR, ANY_RANK, NO_RANK from util import ANY_SUIT, ANY_COLOR, ANY_RANK, NO_RANK
from pysoltk import EVENT_HANDLED, EVENT_PROPAGATE from pysoltk import EVENT_HANDLED, EVENT_PROPAGATE
@ -238,7 +238,6 @@ class Stack:
mapkey = (x, y) mapkey = (x, y)
###assert not game.stackmap.has_key(mapkey) ## can happen in PyJonngg ###assert not game.stackmap.has_key(mapkey) ## can happen in PyJonngg
game.stackmap[mapkey] = id game.stackmap[mapkey] = id
self.init_coord = (x, y)
# #
# setup our pseudo MVC scheme # setup our pseudo MVC scheme
@ -282,15 +281,16 @@ class Stack:
# #
# view # view
# #
self.init_coord = (x, y)
view.x = x view.x = x
view.y = y view.y = y
view.canvas = game.canvas view.canvas = game.canvas
view.CARD_XOFFSET = 0 view.CARD_XOFFSET = 0
view.CARD_YOFFSET = 0 view.CARD_YOFFSET = 0
view.INIT_CARD_OFFSETS = (0,0)
view.INIT_CARD_YOFFSET = 0 # for reallocateCards view.INIT_CARD_YOFFSET = 0 # for reallocateCards
view.group = MfxCanvasGroup(view.canvas) view.group = MfxCanvasGroup(view.canvas)
view.shrink_face_down = 1 view.shrink_face_down = 1
##view.group.move(view.x, view.y)
# image items # image items
view.images = Struct( view.images = Struct(
bottom = None, # canvas item bottom = None, # canvas item
@ -366,6 +366,11 @@ class Stack:
self.CARD_YOFFSET = (oy,) self.CARD_YOFFSET = (oy,)
else: else:
self.CARD_YOFFSET = tuple([int(round(y)) for y in oy]) self.CARD_YOFFSET = tuple([int(round(y)) for y in oy])
# preserve offsets
self.INIT_CARD_OFFSETS = (self.CARD_XOFFSET, self.CARD_YOFFSET) # for resize()
self.INIT_CARD_YOFFSET = self.CARD_YOFFSET # for reallocateCards
if self.can_hide_cards < 0: if self.can_hide_cards < 0:
self.can_hide_cards = self.is_visible self.can_hide_cards = self.is_visible
if self.cap.max_cards < 3: if self.cap.max_cards < 3:
@ -398,7 +403,7 @@ class Stack:
# bottom image # bottom image
if self.is_visible: if self.is_visible:
self.prepareBottom() self.prepareBottom()
self.INIT_CARD_YOFFSET = self.CARD_YOFFSET # for reallocateCards
# stack bottom image # stack bottom image
def prepareBottom(self): def prepareBottom(self):
@ -520,26 +525,6 @@ class Stack:
x, y = self.getPositionFor(card) x, y = self.getPositionFor(card)
card.moveTo(x, y) card.moveTo(x, y)
# move stack to new coords
def moveTo(self, x, y):
dx, dy = x-self.x, y-self.y
self.x, self.y = x, y
for c in self.cards:
x, y = self.getPositionFor(c)
c.moveTo(x, y)
if self.images.bottom:
self.images.bottom.move(dx, dy)
if self.images.redeal:
self.images.redeal.move(dx, dy)
if self.texts.ncards:
self.texts.ncards.move(dx, dy)
if self.texts.rounds:
self.texts.rounds.move(dx, dy)
if self.texts.redeal:
self.texts.redeal.move(dx, dy)
if self.texts.misc:
self.texts.misc.move(dx, dy)
# find card # find card
def _findCard(self, event): def _findCard(self, event):
model, view = self, self model, view = self, self
@ -553,11 +538,12 @@ class Stack:
model, view = self, self model, view = self, self
if cards is None: cards = model.cards if cards is None: cards = model.cards
images = self.game.app.images images = self.game.app.images
cw, ch = images.getSize()
index = -1 index = -1
for i in range(len(cards)): for i in range(len(cards)):
c = cards[i] c = cards[i]
r = (c.x, c.y, c.x + images.CARDW, c.y + images.CARDH) r = (c.x, c.y, c.x + cw, c.y + ch)
if x >= r[0] and x < r[2] and y >= r[1] and y < r[3]: if r[0] <= x < r[2] and r[1] <= y < r[3]:
index = i index = i
return index return index
@ -667,6 +653,10 @@ class Stack:
def resetGame(self): def resetGame(self):
# Called when starting a new game. # Called when starting a new game.
self.CARD_YOFFSET = self.INIT_CARD_YOFFSET self.CARD_YOFFSET = self.INIT_CARD_YOFFSET
self.items.shade_item = None
self.images.shade_img = None
#self.items.bottom = None
#self.images.bottom = None
def __repr__(self): def __repr__(self):
# Return a string for debug print statements. # Return a string for debug print statements.
@ -874,7 +864,7 @@ class Stack:
if not self.canvas.winfo_ismapped(): if not self.canvas.winfo_ismapped():
return False return False
yoffset = self.CARD_YOFFSET[0] yoffset = self.CARD_YOFFSET[0]
cardh = self.game.app.images.CARDH / 2 # 1/2 of a card is visible cardh = self.game.app.images.getSize()[0] / 2 # 1/2 of a card is visible
num_face_up = len([c for c in self.cards if c.face_up]) num_face_up = len([c for c in self.cards if c.face_up])
num_face_down = len(self.cards) - num_face_up num_face_down = len(self.cards) - num_face_up
stack_height = int(self.y + stack_height = int(self.y +
@ -882,13 +872,19 @@ class Stack:
num_face_up * yoffset + num_face_up * yoffset +
cardh) cardh)
visible_height = self.canvas.winfo_height() visible_height = self.canvas.winfo_height()
game_height = self.game.height + 2*self.canvas.ymargin if USE_PIL and self.game.app.opt.auto_scale:
# use visible_height only
game_height = 0
else:
game_height = self.game.height + 2*self.canvas.ymargin
height = max(visible_height, game_height) height = max(visible_height, game_height)
#print 'reallocateCards:', stack_height, height, visible_height, game_height
if stack_height > height: if stack_height > height:
# compact stack # compact stack
n = num_face_down / self.shrink_face_down + num_face_up n = num_face_down / self.shrink_face_down + num_face_up
dy = float(height - self.y - cardh) / n dy = float(height - self.y - cardh) / n
if dy < yoffset: if dy < yoffset:
#print 'compact:', dy
self.CARD_YOFFSET = (dy,) self.CARD_YOFFSET = (dy,)
return True return True
elif stack_height < height: elif stack_height < height:
@ -898,12 +894,62 @@ class Stack:
n = num_face_down / self.shrink_face_down + num_face_up n = num_face_down / self.shrink_face_down + num_face_up
dy = float(height - self.y - cardh) / n dy = float(height - self.y - cardh) / n
dy = min(dy, self.INIT_CARD_YOFFSET[0]) dy = min(dy, self.INIT_CARD_YOFFSET[0])
#print 'expande:', dy
self.CARD_YOFFSET = (dy,) self.CARD_YOFFSET = (dy,)
return True return True
return False return False
def resize(self, xf, yf): def resize(self, xf, yf):
print 'resize', self # resize and move stack
# xf, yf - a multiplicative factor (from the original values)
#print 'Stack.resize:', self, self.is_visible, xf, yf
x0, y0 = self.init_coord
x, y = int(round(x0*xf)), int(round(y0*yf))
self.x, self.y = x, y
# offsets
xoffset = tuple(int(round(i*xf)) for i in self.INIT_CARD_OFFSETS[0])
yoffset = tuple(int(round(i*yf)) for i in self.INIT_CARD_OFFSETS[1])
self.CARD_XOFFSET = xoffset
self.CARD_YOFFSET = yoffset
self.INIT_CARD_YOFFSET = yoffset
#print '* resize offset:', self.INIT_CARD_XOFFSET,
# move cards
for c in self.cards:
cx, cy = self.getPositionFor(c)
c.moveTo(cx, cy)
# ---
if not self.is_visible:
return
# bottom and shade
if self.images.bottom:
img = self.getBottomImage()
self.images.bottom['image'] = img
self.images.bottom.moveTo(x, y)
if self.items.shade_item:
c = self.cards[-1]
img = self.game.app.images.getHighlightedCard(c.deck, c.suit, c.rank)
if img:
self.items.shade_item['image'] = img
self.items.shade_item.moveTo(x, y)
#
def move(item):
ix, iy = item.init_coord
x = int(round(ix*xf))
y = int(round(iy*yf))
item.moveTo(x, y)
# images
if self.images.redeal:
move(self.images.redeal)
# texts
if self.texts.ncards:
move(self.texts.ncards)
if self.texts.rounds:
move(self.texts.rounds)
if self.texts.redeal:
move(self.texts.redeal)
if self.texts.misc:
move(self.texts.misc)
def basicShallHighlightSameRank(self, card): def basicShallHighlightSameRank(self, card):
# by default all open stacks are available for highlighting # by default all open stacks are available for highlighting
@ -1003,14 +1049,14 @@ class Stack:
return 0 return 0
##print self.cards[i] ##print self.cards[i]
self.cards[i].item.tkraise() self.cards[i].item.tkraise()
self.game.canvas.update_idletasks() self.canvas.update_idletasks()
self.game.sleep(self.game.app.opt.timeouts['raise_card']) self.game.sleep(self.game.app.opt.timeouts['raise_card'])
if TOOLKIT == 'tk': if TOOLKIT == 'tk':
self.cards[i].item.lower(self.cards[i+1].item) self.cards[i].item.lower(self.cards[i+1].item)
elif TOOLKIT == 'gtk': elif TOOLKIT == 'gtk':
for c in self.cards[i+1:]: for c in self.cards[i+1:]:
c.tkraise() c.tkraise()
self.game.canvas.update_idletasks() self.canvas.update_idletasks()
return 1 return 1
def controlmiddleclickHandler(self, event): def controlmiddleclickHandler(self, event):
@ -1026,7 +1072,7 @@ class Stack:
if not face_up: if not face_up:
self.cards[i].showFace() self.cards[i].showFace()
self.cards[i].item.tkraise() self.cards[i].item.tkraise()
self.game.canvas.update_idletasks() self.canvas.update_idletasks()
self.game.sleep(self.game.app.opt.timeouts['raise_card']) self.game.sleep(self.game.app.opt.timeouts['raise_card'])
if not face_up: if not face_up:
self.cards[i].showBack() self.cards[i].showBack()
@ -1036,7 +1082,7 @@ class Stack:
elif TOOLKIT == 'gtk': elif TOOLKIT == 'gtk':
for c in self.cards[i+1:]: for c in self.cards[i+1:]:
c.tkraise() c.tkraise()
self.game.canvas.update_idletasks() self.canvas.update_idletasks()
return 1 return 1
def rightclickHandler(self, event): def rightclickHandler(self, event):
@ -1074,8 +1120,7 @@ class Stack:
x0, y0 = drag.stack.getPositionFor(c) x0, y0 = drag.stack.getPositionFor(c)
x1, y1 = c.x, c.y x1, y1 = c.x, c.y
dx, dy = abs(x0-x1), abs(y0-y1) dx, dy = abs(x0-x1), abs(y0-y1)
w = self.game.app.images.CARDW w, h = self.game.app.images.getSize()
h = self.game.app.images.CARDH
if dx > 2*w or dy > 2*h: if dx > 2*w or dy > 2*h:
self.game.animatedMoveTo(drag.stack, drag.stack, self.game.animatedMoveTo(drag.stack, drag.stack,
drag.cards, x0, y0, frames=-1) drag.cards, x0, y0, frames=-1)
@ -1185,7 +1230,7 @@ class Stack:
if self.game.app.opt.mouse_type == 'point-n-click': if self.game.app.opt.mouse_type == 'point-n-click':
if self.acceptsCards(self.game.drag.stack, if self.acceptsCards(self.game.drag.stack,
self.game.drag.cards): self.game.drag.cards):
self.game.canvas.config(cursor=CURSOR_DOWN_ARROW) self.canvas.config(cursor=CURSOR_DOWN_ARROW)
self.current_cursor = CURSOR_DOWN_ARROW self.current_cursor = CURSOR_DOWN_ARROW
self.cursor_changed = True self.cursor_changed = True
else: else:
@ -1203,13 +1248,13 @@ class Stack:
if self.game.app.opt.mouse_type == 'drag-n-drop': if self.game.app.opt.mouse_type == 'drag-n-drop':
return EVENT_HANDLED return EVENT_HANDLED
if self.cursor_changed: if self.cursor_changed:
self.game.canvas.config(cursor='') self.canvas.config(cursor='')
self.current_cursor = '' self.current_cursor = ''
self.cursor_changed = False self.cursor_changed = False
drag_stack = self.game.drag.stack drag_stack = self.game.drag.stack
if self is drag_stack: if self is drag_stack:
x, y = event.x, event.y x, y = event.x, event.y
w, h = self.game.canvas.winfo_width(), self.game.canvas.winfo_height() w, h = self.canvas.winfo_width(), self.canvas.winfo_height()
if x < 0 or y < 0 or x >= w or y >= h: if x < 0 or y < 0 or x >= w or y >= h:
# cancel drag if mouse leave canvas # cancel drag if mouse leave canvas
drag_stack.cancelDrag(event) drag_stack.cancelDrag(event)
@ -1261,10 +1306,11 @@ class Stack:
##sx, sy = 0, 0 ##sx, sy = 0, 0
sx, sy = -images.SHADOW_XOFFSET, -images.SHADOW_YOFFSET sx, sy = -images.SHADOW_XOFFSET, -images.SHADOW_YOFFSET
dx, dy = 0, 0 dx, dy = 0, 0
cw, ch = images.getSize()
if game.app.opt.mouse_type == 'sticky-mouse': if game.app.opt.mouse_type == 'sticky-mouse':
# return cards under mouse # return cards under mouse
dx = event.x - (x_offset+images.CARDW+sx) - game.canvas.xmargin dx = event.x - (x_offset+cw+sx) - game.canvas.xmargin
dy = event.y - (y_offset+images.CARDH+sy) - game.canvas.ymargin dy = event.y - (y_offset+ch+sy) - game.canvas.ymargin
if dx < 0: dx = 0 if dx < 0: dx = 0
if dy < 0: dy = 0 if dy < 0: dy = 0
for s in drag.shadows: for s in drag.shadows:
@ -1316,13 +1362,14 @@ class Stack:
images = self.game.app.images images = self.game.app.images
cx, cy = cards[0].x, cards[0].y cx, cy = cards[0].x, cards[0].y
ddx, ddy = cx-cards[-1].x, cy-cards[-1].y ddx, ddy = cx-cards[-1].x, cy-cards[-1].y
if TOOLKIT == 'tk' and Image and Image.VERSION >= '1.1.7': # use PIL cw, ch = images.getSize()
if USE_PIL:
c0 = cards[-1] c0 = cards[-1]
if self.CARD_XOFFSET[0] < 0: c0 = cards[0] if self.CARD_XOFFSET[0] < 0: c0 = cards[0]
if self.CARD_YOFFSET[0] < 0: c0 = cards[0] if self.CARD_YOFFSET[0] < 0: c0 = cards[0]
img = images.getShadowPIL(self, cards) img = images.getShadowPIL(self, cards)
cx, cy = c0.x + images.CARDW + dx, c0.y + images.CARDH + dy cx, cy = c0.x + cw + dx, c0.y + ch + dy
s = MfxCanvasImage(self.game.canvas, cx, cy, s = MfxCanvasImage(self.canvas, cx, cy,
image=img, anchor=ANCHOR_SE) image=img, anchor=ANCHOR_SE)
s.lower(c0.item) s.lower(c0.item)
return (s,) return (s,)
@ -1346,10 +1393,10 @@ class Stack:
else: else:
return () return ()
if img0 and img1: if img0 and img1:
cx, cy = c0.x + images.CARDW + dx, c0.y + images.CARDH + dy cx, cy = c0.x + cw + dx, c0.y + ch + dy
s1 = MfxCanvasImage(self.game.canvas, cx, cy - img0.height(), s1 = MfxCanvasImage(self.canvas, cx, cy - img0.height(),
image=img1, anchor=ANCHOR_SE) image=img1, anchor=ANCHOR_SE)
s2 = MfxCanvasImage(self.game.canvas, cx, cy, s2 = MfxCanvasImage(self.canvas, cx, cy,
image=img0, anchor=ANCHOR_SE) image=img0, anchor=ANCHOR_SE)
if TOOLKIT == 'tk': if TOOLKIT == 'tk':
s1.lower(c0.item) s1.lower(c0.item)
@ -1412,9 +1459,9 @@ class Stack:
if sstack.cards: if sstack.cards:
card = sstack.cards[-1] card = sstack.cards[-1]
if card.face_up: if card.face_up:
img = images.getShadowCard(card.deck, card.suit, card.rank) img = images.getHighlightedCard(card.deck, card.suit, card.rank)
else: else:
img = images.getShadowBack() img = images.getHighlightedBack()
else: else:
img = images.getShade() img = images.getShade()
if not img: if not img:
@ -1440,11 +1487,11 @@ class Stack:
## self.CARD_YOFFSET != (0,)): ## self.CARD_YOFFSET != (0,)):
## return ## return
card = self.cards[-1] card = self.cards[-1]
img = self.game.app.images.getShadowCard(card.deck, card.suit, card.rank) img = self.game.app.images.getHighlightedCard(card.deck, card.suit, card.rank)
if img is None: if img is None:
return return
#self.game.canvas.update_idletasks() #self.canvas.update_idletasks()
item = MfxCanvasImage(self.game.canvas, card.x, card.y, item = MfxCanvasImage(self.canvas, card.x, card.y,
image=img, anchor=ANCHOR_NW, group=self.group) image=img, anchor=ANCHOR_NW, group=self.group)
#item.tkraise() #item.tkraise()
self.items.shade_item = item self.items.shade_item = item
@ -1463,8 +1510,9 @@ class Stack:
x1, y1 = self.getPositionFor(cards[-1]) x1, y1 = self.getPositionFor(cards[-1])
x0, x1 = min(x1, x0), max(x1, x0) x0, x1 = min(x1, x0), max(x1, x0)
y0, y1 = min(y1, y0), max(y1, y0) y0, y1 = min(y1, y0), max(y1, y0)
x1 = x1 + self.game.app.images.CARDW cw, ch = self.game.app.images.getSize()
y1 = y1 + self.game.app.images.CARDH x1 += cw
y1 += ch
xx0, yy0 = x0, y0 xx0, yy0 = x0, y0
w, h = x1-x0, y1-y0 w, h = x1-x0, y1-y0
# #
@ -1491,7 +1539,7 @@ class Stack:
# #
shade = markImage(shade) shade = markImage(shade)
tkshade = ImageTk.PhotoImage(shade) tkshade = ImageTk.PhotoImage(shade)
im = MfxCanvasImage(self.game.canvas, xx0, yy0, im = MfxCanvasImage(self.canvas, xx0, yy0,
image=tkshade, anchor=ANCHOR_NW, image=tkshade, anchor=ANCHOR_NW,
group=self.group) group=self.group)
drag.shadows.append(im) drag.shadows.append(im)
@ -1512,7 +1560,7 @@ class Stack:
# finish a drag operation # finish a drag operation
def finishDrag(self, event=None): def finishDrag(self, event=None):
if self.game.app.opt.dragcursor: if self.game.app.opt.dragcursor:
self.game.canvas.config(cursor='') self.canvas.config(cursor='')
drag = self.game.drag.copy() drag = self.game.drag.copy()
if self.game.app.opt.mouse_type == 'point-n-click': if self.game.app.opt.mouse_type == 'point-n-click':
drag.stack._stopDrag() drag.stack._stopDrag()
@ -1528,7 +1576,7 @@ class Stack:
# cancel a drag operation # cancel a drag operation
def cancelDrag(self, event=None): def cancelDrag(self, event=None):
if self.game.app.opt.dragcursor: if self.game.app.opt.dragcursor:
self.game.canvas.config(cursor='') self.canvas.config(cursor='')
drag = self.game.drag.copy() drag = self.game.drag.copy()
if self.game.app.opt.mouse_type == 'point-n-click': if self.game.app.opt.mouse_type == 'point-n-click':
drag.stack._stopDrag() drag.stack._stopDrag()
@ -1726,6 +1774,11 @@ class TalonStack(Stack,
Stack.__init__(self, x, y, game, cap=cap) Stack.__init__(self, x, y, game, cap=cap)
self.max_rounds = max_rounds self.max_rounds = max_rounds
self.num_deal = num_deal self.num_deal = num_deal
self.init_redeal = Struct(
top_bottom = None,
img_coord = None,
txt_coord = None,
)
self.resetGame() self.resetGame()
def resetGame(self): def resetGame(self):
@ -1787,22 +1840,34 @@ class TalonStack(Stack,
self.texts.redeal.config(text=t) self.texts.redeal.config(text=t)
self.texts.redeal_str = t self.texts.redeal_str = t
def prepareView(self): def _addRedealImage(self):
Stack.prepareView(self) # add or remove the redeal image/text
if not self.is_visible or self.images.bottom is None: if not self.is_visible or self.images.bottom is None:
return return
if self.images.redeal is not None or self.texts.redeal is not None:
return
if self.game.preview > 1: if self.game.preview > 1:
return return
images = self.game.app.images images = self.game.app.images
cx, cy, ca = self.x + images.CARDW/2, self.y + images.CARDH/2, "center" cw, ch = images.getSize()
if images.CARDW >= 54 and images.CARDH >= 54: cx, cy = self.init_redeal.img_coord
ca = 'center'
tx, ty = self.init_redeal.txt_coord
if self.images.redeal:
self.canvas.delete(self.images.redeal)
self.images.redeal = None
self.images.redeal_img = None
if self.texts.redeal:
self.canvas.delete(self.texts.redeal)
self.texts.redeal = None
self.texts.redeal_str = ''
self.top_bottom = self.init_redeal.top_bottom
if cw >= 60 and ch >= 60:
# add a redeal image above the bottom image # add a redeal image above the bottom image
img = (self.getRedealImages())[self.max_rounds != 1] img = (self.getRedealImages())[self.max_rounds != 1]
if img is not None: if img is not None:
self.images.redeal_img = img self.images.redeal_img = img
self.images.redeal = MfxCanvasImage(self.game.canvas, self.images.redeal = MfxCanvasImage(self.canvas,
cx, cy, image=img, cx, cy, image=img,
anchor="center", anchor="center",
group=self.group) group=self.group)
@ -1812,19 +1877,21 @@ class TalonStack(Stack,
### FIXME ### FIXME
pass pass
self.top_bottom = self.images.redeal self.top_bottom = self.images.redeal
if images.CARDH >= 90: if ch >= 90:
cy, ca = self.y + images.CARDH - 4, "s" cy, ca = ty, "s"
else: else:
ca = None ca = None
font = self.game.app.getFont("canvas_default") font = self.game.app.getFont("canvas_default")
text_width = get_text_width(_('Redeal'), font=font, text_width = get_text_width(_('Redeal'), font=font,
root=self.game.canvas) root=self.canvas)
if images.CARDW >= text_width+4 and ca: if cw >= text_width+4 and ca:
# add a redeal text above the bottom image # add a redeal text below the bottom image
if self.max_rounds != 1: if self.max_rounds != 1:
# FIXME: sometimes canvas do not show the text
#print 'add txt', cx, cy
self.texts.redeal_str = "" self.texts.redeal_str = ""
images = self.game.app.images images = self.game.app.images
self.texts.redeal = MfxCanvasText(self.game.canvas, cx, cy, self.texts.redeal = MfxCanvasText(self.canvas, cx, cy,
anchor=ca, font=font, anchor=ca, font=font,
group=self.group) group=self.group)
if TOOLKIT == 'tk': if TOOLKIT == 'tk':
@ -1834,6 +1901,22 @@ class TalonStack(Stack,
pass pass
self.top_bottom = self.texts.redeal self.top_bottom = self.texts.redeal
def prepareView(self):
Stack.prepareView(self)
if 0:
if not self.is_visible or self.images.bottom is None:
return
if self.images.redeal is not None or self.texts.redeal is not None:
return
if self.game.preview > 1:
return
images = self.game.app.images
self.init_redeal.top_bottom = self.top_bottom
cx, cy, ca = self.x + images.CARDW/2, self.y + images.CARDH/2, "center"
ty = self.y + images.CARDH - 4
self.init_redeal.img_coord = cx, cy
self.init_redeal.txt_coord = cx, ty
getBottomImage = Stack._getTalonBottomImage getBottomImage = Stack._getTalonBottomImage
def getRedealImages(self): def getRedealImages(self):
@ -1853,6 +1936,10 @@ class TalonStack(Stack,
#def getBaseCard(self): #def getBaseCard(self):
# return self._getBaseCard() # return self._getBaseCard()
def resize(self, xf, yf):
self._addRedealImage()
Stack.resize(self, xf, yf)
# A single click deals one card to each of the RowStacks. # A single click deals one card to each of the RowStacks.
class DealRowTalonStack(TalonStack): class DealRowTalonStack(TalonStack):

View file

@ -107,6 +107,17 @@ class _OneImageCard(_HideableCard):
item = self.item item = self.item
item.canvas.tk.call(item.canvas._w, "move", item.id, dx, dy) item.canvas.tk.call(item.canvas._w, "move", item.id, dx, dy)
# for resize
def update(self, id, deck, suit, rank, game):
self._face_image = game.getCardFaceImage(deck, suit, rank)
self._back_image = game.getCardBackImage(deck, suit, rank)
self._shade_image = game.getCardShadeImage()
if self.face_up:
img = self._face_image
else:
img = self._back_image
self.item.config(image=img)
self._active_image = img
# ************************************************************************ # ************************************************************************

View file

@ -31,7 +31,7 @@ import tkFileDialog
# PySol imports # PySol imports
from pysollib.mfxutil import Struct, kwdefault from pysollib.mfxutil import Struct, kwdefault
from pysollib.mfxutil import Image from pysollib.mfxutil import Image, USE_PIL
from pysollib.util import CARDSET from pysollib.util import CARDSET
from pysollib.settings import TITLE, WIN_SYSTEM from pysollib.settings import TITLE, WIN_SYSTEM
from pysollib.settings import SELECT_GAME_MENU from pysollib.settings import SELECT_GAME_MENU
@ -210,6 +210,7 @@ class PysolMenubarTk:
mahjongg_show_removed = Tkinter.BooleanVar(), mahjongg_show_removed = Tkinter.BooleanVar(),
shisen_show_hint = Tkinter.BooleanVar(), shisen_show_hint = Tkinter.BooleanVar(),
sound = Tkinter.BooleanVar(), sound = Tkinter.BooleanVar(),
auto_scale = Tkinter.BooleanVar(),
cardback = Tkinter.IntVar(), cardback = Tkinter.IntVar(),
tabletile = Tkinter.IntVar(), tabletile = Tkinter.IntVar(),
animations = Tkinter.IntVar(), animations = Tkinter.IntVar(),
@ -260,6 +261,7 @@ class PysolMenubarTk:
tkopt.mahjongg_show_removed.set(opt.mahjongg_show_removed) tkopt.mahjongg_show_removed.set(opt.mahjongg_show_removed)
tkopt.shisen_show_hint.set(opt.shisen_show_hint) tkopt.shisen_show_hint.set(opt.shisen_show_hint)
tkopt.sound.set(opt.sound) tkopt.sound.set(opt.sound)
tkopt.auto_scale.set(opt.auto_scale)
tkopt.cardback.set(self.app.cardset.backindex) tkopt.cardback.set(self.app.cardset.backindex)
tkopt.tabletile.set(self.app.tabletile_index) tkopt.tabletile.set(self.app.tabletile_index)
tkopt.animations.set(opt.animations) tkopt.animations.set(opt.animations)
@ -448,6 +450,11 @@ class PysolMenubarTk:
else: else:
menu.add_checkbutton(label=label, variable=self.tkopt.sound, command=self.mOptSoundDialog) menu.add_checkbutton(label=label, variable=self.tkopt.sound, command=self.mOptSoundDialog)
# cardsets # cardsets
if USE_PIL:
submenu = MfxMenu(menu, label=n_("Card si&ze"))
submenu.add_command(label=n_("&Increase the card size"), command=self.mIncreaseCardset, accelerator=m+"+")
submenu.add_command(label=n_("&Decrease the card size"), command=self.mDecreaseCardset, accelerator=m+"-")
submenu.add_checkbutton(label=n_("&Auto scaling"), variable=self.tkopt.auto_scale, command=self.mOptAutoScale, accelerator=m+'0')
#manager = self.app.cardset_manager #manager = self.app.cardset_manager
#n = manager.len() #n = manager.len()
menu.add_command(label=n_("Cards&et..."), command=self.mSelectCardsetDialog, accelerator=m+"E") menu.add_command(label=n_("Cards&et..."), command=self.mSelectCardsetDialog, accelerator=m+"E")
@ -489,7 +496,7 @@ class PysolMenubarTk:
submenu.add_checkbutton(label=n_("Show &statusbar"), variable=self.tkopt.statusbar, command=self.mOptStatusbar) submenu.add_checkbutton(label=n_("Show &statusbar"), variable=self.tkopt.statusbar, command=self.mOptStatusbar)
submenu.add_checkbutton(label=n_("Show &number of cards"), variable=self.tkopt.num_cards, command=self.mOptNumCards) submenu.add_checkbutton(label=n_("Show &number of cards"), variable=self.tkopt.num_cards, command=self.mOptNumCards)
submenu.add_checkbutton(label=n_("Show &help bar"), variable=self.tkopt.helpbar, command=self.mOptHelpbar) submenu.add_checkbutton(label=n_("Show &help bar"), variable=self.tkopt.helpbar, command=self.mOptHelpbar)
menu.add_checkbutton(label=n_("Save games &geometry"), variable=self.tkopt.save_games_geometry, command=self.mOptSaveGamesGeometry) #menu.add_checkbutton(label=n_("Save games &geometry"), variable=self.tkopt.save_games_geometry, command=self.mOptSaveGamesGeometry)
menu.add_checkbutton(label=n_("&Demo logo"), variable=self.tkopt.demo_logo, command=self.mOptDemoLogo) menu.add_checkbutton(label=n_("&Demo logo"), variable=self.tkopt.demo_logo, command=self.mOptDemoLogo)
menu.add_checkbutton(label=n_("Startup splash sc&reen"), variable=self.tkopt.splashscreen, command=self.mOptSplashscreen) menu.add_checkbutton(label=n_("Startup splash sc&reen"), variable=self.tkopt.splashscreen, command=self.mOptSplashscreen)
### menu.add_separator() ### menu.add_separator()
@ -538,6 +545,11 @@ class PysolMenubarTk:
self._bindKey("", "F3", self.mFindCard) self._bindKey("", "F3", self.mFindCard)
self._bindKey(ctrl, "d", self.mDemo) self._bindKey(ctrl, "d", self.mDemo)
self._bindKey(ctrl, "e", self.mSelectCardsetDialog) self._bindKey(ctrl, "e", self.mSelectCardsetDialog)
if USE_PIL:
self._bindKey(ctrl, "plus", self.mIncreaseCardset)
self._bindKey(ctrl, "equal", self.mIncreaseCardset)
self._bindKey(ctrl, "minus", self.mDecreaseCardset)
self._bindKey(ctrl, "0", self.mOptAutoScale)
self._bindKey(ctrl, "b", self.mOptChangeCardback) # undocumented self._bindKey(ctrl, "b", self.mOptChangeCardback) # undocumented
self._bindKey(ctrl, "i", self.mOptChangeTableTile) # undocumented self._bindKey(ctrl, "i", self.mOptChangeTableTile) # undocumented
self._bindKey(ctrl, "p", self.mOptPlayerOptions) # undocumented self._bindKey(ctrl, "p", self.mOptPlayerOptions) # undocumented
@ -1134,6 +1146,56 @@ class PysolMenubarTk:
self.app.opt.shisen_show_hint = self.tkopt.shisen_show_hint.get() self.app.opt.shisen_show_hint = self.tkopt.shisen_show_hint.get()
##self.game.updateMenus() ##self.game.updateMenus()
def _updateCardSize(self):
geom = (self.app.canvas.winfo_width(),
self.app.canvas.winfo_height())
self.app.opt.game_geometry = geom
self.app.game.resizeGame()
if self.app.opt.auto_scale:
w, h = self.app.opt.game_geometry
self.app.canvas.setInitialSize(w, h, scrollregion=False)
else:
w = int(round(self.app.game.width * self.app.opt.scale_x))
h = int(round(self.app.game.height * self.app.opt.scale_y))
self.app.canvas.setInitialSize(w, h)
self.app.top.wm_geometry("") # cancel user-specified geometry
##self.app.top.update_idletasks()
def mIncreaseCardset(self, *event):
if self._cancelDrag(break_pause=True): return
if self.app.opt.scale_x < 4:
self.app.opt.scale_x += 0.1
else:
return
if self.app.opt.scale_y < 4:
self.app.opt.scale_y += 0.1
else:
return
self.app.opt.auto_scale = False
self.tkopt.auto_scale.set(False)
self._updateCardSize()
def mDecreaseCardset(self, *event):
if self._cancelDrag(break_pause=True): return
if self.app.opt.scale_x > 0.5:
self.app.opt.scale_x -= 0.1
else:
return
if self.app.opt.scale_y > 0.5:
self.app.opt.scale_y -= 0.1
else:
return
self.app.opt.auto_scale = False
self.tkopt.auto_scale.set(False)
self._updateCardSize()
def mOptAutoScale(self, *event):
if self._cancelDrag(break_pause=True): return
auto_scale = not self.app.opt.auto_scale
self.app.opt.auto_scale = auto_scale
self.tkopt.auto_scale.set(auto_scale)
self._updateCardSize()
def mSelectCardsetDialog(self, *event): def mSelectCardsetDialog(self, *event):
if self._cancelDrag(break_pause=False): return if self._cancelDrag(break_pause=False): return
t = CARDSET t = CARDSET
@ -1141,14 +1203,30 @@ class PysolMenubarTk:
d = SelectCardsetDialogWithPreview(self.top, title=_("Select ")+t, d = SelectCardsetDialogWithPreview(self.top, title=_("Select ")+t,
app=self.app, manager=self.app.cardset_manager, key=key) app=self.app, manager=self.app.cardset_manager, key=key)
cs = self.app.cardset_manager.get(d.key) cs = self.app.cardset_manager.get(d.key)
if cs is None or d.key == self.app.cardset.index: if d.status != 0 or d.button != 0 or cs is None:
return return
if d.status == 0 and d.button == 0 and d.key >= 0: if USE_PIL:
changed = (self.app.opt.scale_x,
self.app.opt.scale_y,
self.app.opt.auto_scale,
self.app.opt.preserve_aspect_ratio) != d.scale_values
else:
changed = False
if d.key == self.app.cardset.index and not changed:
return
if d.key >= 0:
self.app.nextgame.cardset = cs self.app.nextgame.cardset = cs
if d.button == 0: if USE_PIL:
self._cancelDrag() (self.app.opt.scale_x,
self.game.endGame(bookmark=1) self.app.opt.scale_y,
self.game.quitGame(bookmark=1) self.app.opt.auto_scale,
self.app.opt.preserve_aspect_ratio) = d.scale_values
if not self.app.opt.auto_scale:
self.app.images.resize(self.app.opt.scale_x,
self.app.opt.scale_y)
self._cancelDrag()
self.game.endGame(bookmark=1)
self.game.quitGame(bookmark=1)
def _mOptCardback(self, index): def _mOptCardback(self, index):
if self._cancelDrag(break_pause=False): return if self._cancelDrag(break_pause=False): return
@ -1323,7 +1401,7 @@ class PysolMenubarTk:
self.game.showStackDesc() self.game.showStackDesc()
# #
# Tlie # Tile (ttk)
# #
def mOptTheme(self, *event): def mOptTheme(self, *event):

View file

@ -29,13 +29,13 @@ import Tkinter
import ttk import ttk
# PySol imports # PySol imports
from pysollib.mfxutil import KwStruct from pysollib.mfxutil import KwStruct, USE_PIL
from pysollib.util import CARDSET from pysollib.util import CARDSET
from pysollib.resource import CSI from pysollib.resource import CSI
# Toolkit imports # Toolkit imports
from tkutil import loadImage from tkutil import loadImage
from tkwidget import MfxDialog, MfxScrolledCanvas from tkwidget import MfxDialog, MfxScrolledCanvas, PysolScale
from tkcanvas import MfxCanvasImage from tkcanvas import MfxCanvasImage
from selecttree import SelectDialogTreeLeaf, SelectDialogTreeNode from selecttree import SelectDialogTreeLeaf, SelectDialogTreeNode
from selecttree import SelectDialogTreeData, SelectDialogTreeCanvas from selecttree import SelectDialogTreeData, SelectDialogTreeCanvas
@ -179,6 +179,7 @@ class SelectCardsetDialogWithPreview(MfxDialog):
key = manager.getSelected() key = manager.getSelected()
self.manager = manager self.manager = manager
self.key = key self.key = key
self.app = app
#padx, pady = kw.padx, kw.pady #padx, pady = kw.padx, kw.pady
padx, pady = 5, 5 padx, pady = 5, 5
if self.TreeDataHolder_Class.data is None: if self.TreeDataHolder_Class.data is None:
@ -186,7 +187,7 @@ class SelectCardsetDialogWithPreview(MfxDialog):
# #
self.top.wm_minsize(400, 200) self.top.wm_minsize(400, 200)
if self.top.winfo_screenwidth() >= 800: if self.top.winfo_screenwidth() >= 800:
w1, w2 = 216, 400 w1, w2 = 240, 400
else: else:
w1, w2 = 200, 300 w1, w2 = 200, 300
paned_window = ttk.PanedWindow(top_frame, orient='horizontal') paned_window = ttk.PanedWindow(top_frame, orient='horizontal')
@ -199,7 +200,56 @@ class SelectCardsetDialogWithPreview(MfxDialog):
self.tree = self.Tree_Class(self, left_frame, key=key, self.tree = self.Tree_Class(self, left_frame, key=key,
default=kw.default, default=kw.default,
font=font, width=w1) font=font, width=w1)
self.tree.frame.pack(fill='both', expand=True, padx=padx, pady=pady) self.tree.frame.grid(row=0, column=0, sticky='nsew',
padx=padx, pady=pady)
if USE_PIL:
#
var = Tkinter.DoubleVar()
var.set(app.opt.scale_x)
self.scale_x = PysolScale(
left_frame, label=_('Scale X:'),
from_=0.5, to=4.0, resolution=0.1,
orient='horizontal', variable=var,
value=app.opt.scale_x,
command=self._updateScale)
self.scale_x.grid(row=1, column=0, sticky='ew', padx=padx, pady=pady)
#
var = Tkinter.DoubleVar()
var.set(app.opt.scale_y)
self.scale_y = PysolScale(
left_frame, label=_('Scale Y:'),
from_=0.5, to=4.0, resolution=0.1,
orient='horizontal', variable=var,
value=app.opt.scale_y,
command=self._updateScale)
self.scale_y.grid(row=2, column=0, sticky='ew', padx=padx, pady=pady)
#
self.auto_scale = Tkinter.BooleanVar()
self.auto_scale.set(app.opt.auto_scale)
check = ttk.Checkbutton(
left_frame, text=_('Auto scaling'),
variable=self.auto_scale,
takefocus=False,
command=self._updateAutoScale
)
check.grid(row=3, column=0, columnspan=2, sticky='ew',
padx=padx, pady=pady)
#
self.preserve_aspect = Tkinter.BooleanVar()
self.preserve_aspect.set(app.opt.preserve_aspect_ratio)
self.aspect_check = ttk.Checkbutton(
left_frame, text=_('Preserve aspect ratio'),
variable=self.preserve_aspect,
takefocus=False,
#command=self._updateScale
)
self.aspect_check.grid(row=4, column=0, sticky='ew',
padx=padx, pady=pady)
self._updateAutoScale()
#
left_frame.rowconfigure(0, weight=1)
left_frame.columnconfigure(0, weight=1)
#
self.preview = MfxScrolledCanvas(right_frame, width=w2) self.preview = MfxScrolledCanvas(right_frame, width=w2)
self.preview.setTile(app, app.tabletile_index, force=True) self.preview.setTile(app, app.tabletile_index, force=True)
self.preview.pack(fill='both', expand=True, padx=padx, pady=pady) self.preview.pack(fill='both', expand=True, padx=padx, pady=pady)
@ -207,6 +257,7 @@ class SelectCardsetDialogWithPreview(MfxDialog):
# create a preview of the current state # create a preview of the current state
self.preview_key = -1 self.preview_key = -1
self.preview_images = [] self.preview_images = []
self.scale_images = []
self.updatePreview(key) self.updatePreview(key)
# #
focus = self.createButtons(bottom_frame, kw) focus = self.createButtons(bottom_frame, kw)
@ -233,6 +284,20 @@ class SelectCardsetDialogWithPreview(MfxDialog):
if button in (0, 1): # Load/Cancel if button in (0, 1): # Load/Cancel
self.key = self.tree.selection_key self.key = self.tree.selection_key
self.tree.n_expansions = 1 # save xyview in any case self.tree.n_expansions = 1 # save xyview in any case
if USE_PIL:
auto_scale = bool(self.auto_scale.get())
if button == 1:
self.app.menubar.tkopt.auto_scale.set(auto_scale)
if auto_scale:
self.scale_values = (self.app.opt.scale_x,
self.app.opt.scale_y,
auto_scale,
bool(self.preserve_aspect.get()))
else:
self.scale_values = (self.scale_x.get(),
self.scale_y.get(),
auto_scale,
self.app.opt.preserve_aspect_ratio)
if button == 10: # Info if button == 10: # Info
cs = self.manager.get(self.tree.selection_key) cs = self.manager.get(self.tree.selection_key)
if not cs: if not cs:
@ -243,9 +308,24 @@ class SelectCardsetDialogWithPreview(MfxDialog):
return return
MfxDialog.mDone(self, button) MfxDialog.mDone(self, button)
def updatePreview(self, key): def _updateAutoScale(self, v=None):
if self.auto_scale.get():
self.aspect_check.config(state='normal')
self.scale_x.state('disabled')
self.scale_y.state('disabled')
else:
self.aspect_check.config(state='disabled')
self.scale_x.state('!disabled')
self.scale_y.state('!disabled')
def _updateScale(self, v):
self.updatePreview()
def updatePreview(self, key=None):
if key == self.preview_key: if key == self.preview_key:
return return
if key is None:
key = self.key
canvas = self.preview.canvas canvas = self.preview.canvas
canvas.deleteAllItems() canvas.deleteAllItems()
self.preview_images = [] self.preview_images = []
@ -264,7 +344,16 @@ class SelectCardsetDialogWithPreview(MfxDialog):
self.preview_images = [] self.preview_images = []
return return
i, x, y, sx, sy, dx, dy = 0, 10, 10, 0, 0, cs.CARDW + 10, cs.CARDH + 10 i, x, y, sx, sy, dx, dy = 0, 10, 10, 0, 0, cs.CARDW + 10, cs.CARDH + 10
if USE_PIL:
xf = self.scale_x.get()
yf = self.scale_y.get()
dx = int(dx*xf)
dy = int(dy*yf)
self.scale_images = []
for image in self.preview_images: for image in self.preview_images:
if USE_PIL:
image = image.resize(xf, yf)
self.scale_images.append(image)
MfxCanvasImage(canvas, x, y, anchor="nw", image=image) MfxCanvasImage(canvas, x, y, anchor="nw", image=image)
sx, sy = max(x, sx), max(y, sy) sx, sy = max(x, sx), max(y, sy)
i = i + 1 i = i + 1
@ -272,13 +361,12 @@ class SelectCardsetDialogWithPreview(MfxDialog):
x, y = 10, y + dy x, y = 10, y + dy
else: else:
x = x + dx x = x + dx
## canvas.config(scrollregion=(0, 0, sx+dx, sy+dy))
## canvas.config(width=sx+dx, height=sy+dy)
canvas.config(scrollregion=(0, 0, sx+dx, sy+dy), canvas.config(scrollregion=(0, 0, sx+dx, sy+dy),
width=sx+dx, height=sy+dy) width=sx+dx, height=sy+dy)
#canvas.config(xscrollincrement=dx, yscrollincrement=dy) #canvas.config(xscrollincrement=dx, yscrollincrement=dy)
canvas.event_generate('<Configure>') # update bg image canvas.event_generate('<Configure>') # update bg image
self.preview_key = key self.preview_key = key
self.key = key
class SelectCardsetByTypeDialogWithPreview(SelectCardsetDialogWithPreview): class SelectCardsetByTypeDialogWithPreview(SelectCardsetDialogWithPreview):

View file

@ -58,14 +58,15 @@ class MfxCanvasGroup(Canvas.Group):
return self.canvas.tk.splitlist(self._do("gettags")) return self.canvas.tk.splitlist(self._do("gettags"))
class MfxCanvasImage(Canvas.ImageItem): class MfxCanvasImage(Canvas.ImageItem):
def __init__(self, canvas, *args, **kwargs): def __init__(self, canvas, x, y, **kwargs):
self.init_coord = x, y
group = None group = None
if 'group' in kwargs: if 'group' in kwargs:
group = kwargs['group'] group = kwargs['group']
del kwargs['group'] del kwargs['group']
if 'image' in kwargs: if 'image' in kwargs:
self._image = kwargs['image'] self._image = kwargs['image']
Canvas.ImageItem.__init__(self, canvas, *args, **kwargs) Canvas.ImageItem.__init__(self, canvas, x, y, **kwargs)
if group: if group:
self.addtag(group) self.addtag(group)
def moveTo(self, x, y): def moveTo(self, x, y):
@ -90,6 +91,8 @@ class MfxCanvasRectangle(Canvas.Rectangle):
class MfxCanvasText(Canvas.CanvasText): class MfxCanvasText(Canvas.CanvasText):
def __init__(self, canvas, x, y, preview=-1, **kwargs): def __init__(self, canvas, x, y, preview=-1, **kwargs):
self.init_coord = x, y
self.x, self.y = x, y
if preview < 0: if preview < 0:
preview = canvas.preview preview = canvas.preview
if preview > 1: if preview > 1:
@ -105,6 +108,10 @@ class MfxCanvasText(Canvas.CanvasText):
canvas._text_items.append(self) canvas._text_items.append(self)
if group: if group:
self.addtag(group) self.addtag(group)
def moveTo(self, x, y):
dx, dy = x - self.x, y - self.y
self.x, self.y = x, y
self.move(dx, dy)
# ************************************************************************ # ************************************************************************
@ -229,17 +236,24 @@ class MfxCanvas(Tkinter.Canvas):
# #
# #
def setInitialSize(self, width, height): def setInitialSize(self, width, height, margins=True, scrollregion=True):
##print 'setInitialSize:', width, height #print 'Canvas.setInitialSize:', width, height, scrollregion
if self.preview: if self.preview:
self.config(width=width, height=height, self.config(width=width, height=height,
scrollregion=(0, 0, width, height)) scrollregion=(0, 0, width, height))
else: else:
# add margins # add margins
##dx, dy = 40, 40
dx, dy = self.xmargin, self.ymargin dx, dy = self.xmargin, self.ymargin
self.config(width=dx+width+dx, height=dy+height+dy, if margins:
scrollregion=(-dx, -dy, width+dx, height+dy)) w, h = dx+width+dx, dy+height+dy
else:
w, h = width, height
self.config(width=w, height=h)
if scrollregion:
self.config(scrollregion=(-dx, -dy, width+dx, height+dy))
else:
# no scrolls
self.config(scrollregion=(-dx, -dy, dx, dy))
# #

View file

@ -41,6 +41,7 @@ __all__ = ['wm_withdraw',
'shadowImage', 'shadowImage',
'markImage', 'markImage',
'createBottom', 'createBottom',
'resizeBottom',
'get_text_width', 'get_text_width',
] ]
@ -248,11 +249,15 @@ def after_cancel(t):
if Image: if Image:
class PIL_Image(ImageTk.PhotoImage): class PIL_Image(ImageTk.PhotoImage):
def __init__(self, file=None, image=None): def __init__(self, file=None, image=None, pil_image_orig=None):
if file: if file:
image = Image.open(file).convert('RGBA') image = Image.open(file).convert('RGBA')
ImageTk.PhotoImage.__init__(self, image) ImageTk.PhotoImage.__init__(self, image)
self._pil_image = image self._pil_image = image
if pil_image_orig:
self._pil_image_orig = pil_image_orig
else:
self._pil_image_orig = image
def subsample(self, r): def subsample(self, r):
im = self._pil_image im = self._pil_image
w, h = im.size w, h = im.size
@ -260,6 +265,11 @@ if Image:
im = im.resize((w, h)) im = im.resize((w, h))
im = PIL_Image(image=im) im = PIL_Image(image=im)
return im return im
def resize(self, xf, yf):
w, h = self._pil_image_orig.size
w0, h0 = int(w*xf), int(h*yf)
im = self._pil_image_orig.resize((w0,h0), Image.ANTIALIAS)
return PIL_Image(image=im, pil_image_orig=self._pil_image_orig)
def makeImage(file=None, data=None, dither=None, alpha=None): def makeImage(file=None, data=None, dither=None, alpha=None):
@ -360,14 +370,11 @@ def markImage(image):
out = Image.composite(tmp, image, image) out = Image.composite(tmp, image, image)
return out return out
def createBottom(image, color='white', backfile=None): def _createBottomImage(image, color='white', backfile=None):
if not hasattr(image, '_pil_image'):
return None
im = image._pil_image
th = 1 # thickness th = 1 # thickness
sh = Image.new('RGBA', im.size, color) sh = Image.new('RGBA', image.size, color)
out = Image.composite(sh, im, im) out = Image.composite(sh, image, image)
w, h = im.size w, h = image.size
size = (w-th*2, h-th*2) size = (w-th*2, h-th*2)
tmp = Image.new('RGBA', size, color) tmp = Image.new('RGBA', size, color)
tmp.putalpha(60) tmp.putalpha(60)
@ -376,15 +383,27 @@ def createBottom(image, color='white', backfile=None):
if backfile: if backfile:
back = Image.open(backfile).convert('RGBA') back = Image.open(backfile).convert('RGBA')
w0, h0 = back.size w0, h0 = back.size
w1, h1 = im.size w1, h1 = w, h
a = min(float(w1)/w0, float(h1)/h0) a = min(float(w1)/w0, float(h1)/h0)
a = a*0.9 a = a*0.9
w0, h0 = int(w0*a), int(h0*a) w0, h0 = int(w0*a), int(h0*a)
back = back.resize((w0,h0), Image.ANTIALIAS) back = back.resize((w0,h0), Image.ANTIALIAS)
x, y = (w1 - w0) / 2, (h1 - h0) / 2 x, y = (w1 - w0) / 2, (h1 - h0) / 2
out.paste(back, (x,y), back) out.paste(back, (x,y), back)
return out
def createBottom(maskimage, color='white', backfile=None):
if not hasattr(maskimage, '_pil_image'):
return None
maskimage = maskimage._pil_image
out = _createBottomImage(maskimage, color, backfile)
return PIL_Image(image=out) return PIL_Image(image=out)
def resizeBottom(image, maskimage, color='white', backfile=None):
maskimage = maskimage._pil_image
out = _createBottomImage(maskimage, color, backfile)
image['image'] = out
# ************************************************************************ # ************************************************************************
# * font utils # * font utils

View file

@ -667,7 +667,7 @@ class StackDesc:
font = game.app.getFont('canvas_small') font = game.app.getFont('canvas_small')
##print self.app.cardset.CARDW, self.app.images.CARDW ##print self.app.cardset.CARDW, self.app.images.CARDW
cardw = game.app.images.CARDW cardw = game.app.images.getSize()[0]
x, y = stack.x+cardw/2, stack.y x, y = stack.x+cardw/2, stack.y
text = stack.getHelp()+'\n'+stack.getBaseCard() text = stack.getHelp()+'\n'+stack.getBaseCard()
text = text.strip() text = text.strip()
@ -715,30 +715,26 @@ class MyPysolScale:
kw['from_'] = kw['from_']/self.resolution kw['from_'] = kw['from_']/self.resolution
if 'to' in kw: if 'to' in kw:
kw['to'] = kw['to']/self.resolution kw['to'] = kw['to']/self.resolution
if 'command' in kw:
self.command = kw['command']
else:
self.command = None
if 'variable' in kw: if 'variable' in kw:
self.variable = kw['variable'] self.variable = kw['variable']
del kw['variable'] del kw['variable']
else: else:
self.variable = None self.variable = None
value = None
if 'value' in kw: if 'value' in kw:
value = kw['value'] value = kw['value']
del kw['value'] del kw['value']
if self.variable: elif self.variable:
self.variable.set(value) value = self.variable.get()
else: self.value = value
value = None self.command = command = None
if self.variable: if 'command' in kw:
value = self.variable.get() command = kw['command']
if self.variable:
self.variable.trace('w', self._trace_var)
kw['command'] = self._scale_command kw['command'] = self._scale_command
if 'label' in kw: if 'label' in kw:
self.label_text = kw['label'] self.label_text = kw['label']
width = len(self.label_text)+4 width = len(self.label_text)+4
#width = None
del kw['label'] del kw['label']
else: else:
self.label_text = None self.label_text = None
@ -753,13 +749,16 @@ class MyPysolScale:
self.scale = ttk.Scale(self.frame, **kw) self.scale = ttk.Scale(self.frame, **kw)
self.scale.pack(side=side, expand=True, fill='both', pady=4) self.scale.pack(side=side, expand=True, fill='both', pady=4)
if self.variable:
self.variable.trace('w', self._trace_var)
if value is not None: if value is not None:
if self.variable:
self.variable.set(self._round(value))
self._set_text(self._round(value)) self._set_text(self._round(value))
if self.variable:
self.variable.set(value)
self.command = command
def _round(self, value): def _round(self, value):
return int(float(value)/self.resolution)*self.resolution return int(round(float(value)/self.resolution))*self.resolution
def _trace_var(self, *args): def _trace_var(self, *args):
self.scale.set(float(self.variable.get())/self.resolution) self.scale.set(float(self.variable.get())/self.resolution)
@ -775,8 +774,9 @@ class MyPysolScale:
v = self._round(float(value)*self.resolution) v = self._round(float(value)*self.resolution)
self._set_text(v) self._set_text(v)
self.variable.set(v) self.variable.set(v)
if self.command: if value != self.value and self.command:
self.command(value) self.command(value)
self.value = value
def pack(self, **kw): def pack(self, **kw):
self.frame.pack(**kw) self.frame.pack(**kw)
@ -787,6 +787,15 @@ class MyPysolScale:
self.scale.configure(**kw) self.scale.configure(**kw)
config = configure config = configure
def state(self, v):
self.scale.state(statespec=(v,))
self.label.state(statespec=(v,))
def get(self):
return self.variable.get()
def set(self, v):
self.variable.set(v)
class TkinterScale(Tkinter.Scale): class TkinterScale(Tkinter.Scale):
def __init__(self, parent, **kw): def __init__(self, parent, **kw):