diff --git a/pysollib/game/__init__.py b/pysollib/game/__init__.py index de1142f0..29be3c5d 100644 --- a/pysollib/game/__init__.py +++ b/pysollib/game/__init__.py @@ -298,12 +298,14 @@ class StackRegions(NewStruct): # init info (at the start) init_info = attr.ib(factory=list) - def calc_info(self, xf, yf): + def calc_info(self, xf, yf, widthpad=0, heightpad=0): """docstring for calc_info""" info = [] for stacks, rect in self.init_info: - newrect = (int(round(rect[0]*xf)), int(round(rect[1]*yf)), - int(round(rect[2]*xf)), int(round(rect[3]*yf))) + newrect = (int(round((rect[0] + widthpad) * xf)), + int(round((rect[1] + heightpad) * yf)), + int(round((rect[2] + widthpad) * xf)), + int(round((rect[3] + heightpad) * yf))) info.append((stacks, newrect)) self.info = tuple(info) @@ -815,6 +817,7 @@ class Game(object): if dealer: dealer() else: + self.resizeGame() self.startGame() self.startMoves() for stack in self.allstacks: @@ -983,23 +986,24 @@ class Game(object): self.newGame(restart=1, random=self.random) def resizeImages(self, manually=False): + if self.canvas.winfo_ismapped(): + # apparent size of canvas + vw = self.canvas.winfo_width() + 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, 1, 1, 0, 0 + # requested size of canvas (createGame -> setSize) + iw, ih = self.init_size + # resizing images and cards if (self.app.opt.auto_scale or (self.app.opt.spread_stacks and not manually)): - if self.canvas.winfo_ismapped(): - # apparent size of canvas - vw = self.canvas.winfo_width() - 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, 1, 1 - # requested size of canvas (createGame -> setSize) - iw, ih = self.init_size # calculate factor of resizing xf = float(vw)/iw yf = float(vh)/ih @@ -1008,13 +1012,29 @@ class Game(object): xf = yf = min(xf, yf) else: xf, yf = self.app.opt.scale_x, self.app.opt.scale_y + cw, ch = self.getCenterOffset(vw, vh, iw, ih, xf, yf) if (not self.app.opt.spread_stacks or manually): # 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, self.app.images._xfactor, self.app.images._yfactor + return xf, yf, self.app.images._xfactor, self.app.images._yfactor, \ + cw, ch + + def getCenterOffset(self, vw, vh, iw, ih, xf, yf): + if (not self.app.opt.center_layout or self.app.opt.spread_stacks or + (self.app.opt.auto_scale and not + self.app.opt.preserve_aspect_ratio)): + return 0, 0 + if ((vw > iw and vh > ih) or self.app.opt.auto_scale): + return (vw / xf - iw) / 2, (vh / yf - ih) / 2 + elif (vw >= iw and vh < ih): + return (vw / xf - iw) / 2, 0 + elif (vw < iw and vh >= ih): + return 0, (vh / yf - ih) / 2 + else: + return 0, 0 def resizeGame(self, card_size_manually=False): # if self.busy: @@ -1022,10 +1042,11 @@ class Game(object): if not USE_PIL: return self.deleteStackDesc() - xf, yf, xf0, yf0 = self.resizeImages(manually=card_size_manually) + xf, yf, xf0, yf0, cw, ch = \ + self.resizeImages(manually=card_size_manually) for stack in self.allstacks: x0, y0 = stack.init_coord - x, y = int(round(x0*xf)), int(round(y0*yf)) + x, y = int(round(x0 * xf) + cw), int(round(y0 * yf) + ch) if (self.app.opt.spread_stacks): # Do not move Talons @@ -1039,27 +1060,28 @@ class Game(object): if stack is self.s.talon: # stack.init_coord=(x, y) if card_size_manually: - stack.resize(xf, yf0) + stack.resize(xf, yf0, widthpad=cw, heightpad=ch) else: - stack.resize(xf0, yf0) + stack.resize(xf0, yf0, widthpad=cw, heightpad=ch) else: - stack.resize(xf, yf0) + stack.resize(xf, yf0, widthpad=cw, heightpad=ch) else: - stack.resize(xf, yf) + stack.resize(xf, yf, widthpad=cw, heightpad=ch) stack.updatePositions() - self.regions.calc_info(xf, yf) + self.regions.calc_info(xf, yf, widthpad=cw, heightpad=ch) # 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)) + x, y = int(round((init_coord[0] + cw) * xf)), \ + int(round((init_coord[1] + ch) * 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)) + x, y = int(round((init_coord[0] + cw) * xf)), \ + int(round((init_coord[1] + ch) * yf)) self.canvas.coords(item, x, y) def createRandom(self, random): @@ -1312,7 +1334,9 @@ class Game(object): return if not self.canvas: return - if not self.app.opt.auto_scale: + if (not self.app.opt.auto_scale and + not self.app.opt.spread_stacks and + not self.app.opt.center_layout): return if self.preview: return diff --git a/pysollib/options.py b/pysollib/options.py index 172ff645..1d5042d6 100644 --- a/pysollib/options.py +++ b/pysollib/options.py @@ -439,6 +439,7 @@ class Options: self.scale_y = 1.0 self.auto_scale = False self.spread_stacks = False + self.center_layout = True self.preserve_aspect_ratio = True # solver self.solver_presets = [ diff --git a/pysollib/stack.py b/pysollib/stack.py index 5a867966..06d0cdfc 100644 --- a/pysollib/stack.py +++ b/pysollib/stack.py @@ -851,11 +851,15 @@ class Stack: return True return False - def resize(self, xf, yf): + def resize(self, xf, yf, widthpad=0, heightpad=0): # 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 + if (x0 > 0): + x0 += widthpad + if (y0 > 0): + y0 += heightpad x, y = int(round(x0*xf)), int(round(y0*yf)) self.x, self.y = x, y # offsets @@ -893,8 +897,8 @@ class Stack: # move the items def move(item): ix, iy = item.init_coord - x = int(round(ix*xf)) - y = int(round(iy*yf)) + x = int(round((ix + widthpad) * xf)) + y = int(round((iy + heightpad) * yf)) item.moveTo(x, y) # images if self.images.redeal: @@ -1967,9 +1971,9 @@ class TalonStack(Stack, # def getBaseCard(self): # return self._getBaseCard() - def resize(self, xf, yf): + def resize(self, xf, yf, widthpad=0, heightpad=0): self._addRedealImage() - Stack.resize(self, xf, yf) + Stack.resize(self, xf, yf, widthpad=widthpad, heightpad=heightpad) # A single click deals one card to each of the RowStacks. diff --git a/pysollib/ui/tktile/menubar.py b/pysollib/ui/tktile/menubar.py index 294f0649..8b1085b6 100644 --- a/pysollib/ui/tktile/menubar.py +++ b/pysollib/ui/tktile/menubar.py @@ -172,6 +172,7 @@ class PysolMenubarTkCommon: sound=tkinter.BooleanVar(), auto_scale=tkinter.BooleanVar(), spread_stacks=tkinter.BooleanVar(), + center_layout=tkinter.BooleanVar(), cardback=tkinter.IntVar(), tabletile=tkinter.IntVar(), animations=tkinter.IntVar(), @@ -224,6 +225,7 @@ class PysolMenubarTkCommon: tkopt.sound.set(opt.sound) tkopt.auto_scale.set(opt.auto_scale) tkopt.spread_stacks.set(opt.spread_stacks) + tkopt.center_layout.set(opt.center_layout) tkopt.cardback.set(self.app.cardset.backindex) tkopt.tabletile.set(self.app.tabletile_index) tkopt.animations.set(opt.animations) @@ -530,9 +532,13 @@ class PysolMenubarTkCommon: submenu.add_checkbutton( label=n_("&Auto scaling"), variable=self.tkopt.auto_scale, command=self.mOptAutoScale, accelerator=m+'0') + submenu = MfxMenu(menu, label=n_("Card la&yout")) submenu.add_checkbutton( label=n_("&Spread stacks"), variable=self.tkopt.spread_stacks, command=self.mOptSpreadStacks) + submenu.add_checkbutton( + label=n_("&Center layout"), variable=self.tkopt.center_layout, + command=self.mOptCenterLayout) # manager = self.app.cardset_manager # n = manager.len() menu.add_command( @@ -1509,6 +1515,12 @@ Unsupported game for import. self.tkopt.spread_stacks.set(spread_stacks) self._updateCardSize() + def mOptCenterLayout(self, *event): + if self._cancelDrag(break_pause=True): + return + self.app.opt.center_layout = not self.app.opt.center_layout + self._updateCardSize() + def _mOptCardback(self, index): if self._cancelDrag(break_pause=False): return