Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pysollib/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,10 @@ def wm_save_state(self):
self.opt.wm_maximized = True
elif s == "normal":
self.opt.wm_maximized = False
if s == "normal" and not self.opt.wm_fullscreen:
self.opt.window_geometry = (
self.top.winfo_x(), self.top.winfo_y(),
self.top.winfo_width(), self.top.winfo_height())

def wm_withdraw(self):
if self.intro.progress:
Expand Down
8 changes: 5 additions & 3 deletions pysollib/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ def help_html(app, document, dir_, top=None):
return None
if top is None:
top = app.top
parent = top
try:
doc = app.dataloader.findFile(document, dir_)
if help_html_index is None:
Expand Down Expand Up @@ -149,10 +150,11 @@ def help_html(app, document, dir_, top=None):
h = int(sh * .8)
w = min(650, int(sw * .8))
if TOOLKIT == "tk":
th = int(top.winfo_rooty() - top.winfo_y())
from pysollib.ui.tktile.tkutil import placeOverParent
top.wm_minsize(w, min(200, h))
top.geometry("%dx%d+%d+%d" % (w, h, (sw - w) / 2,
((sh - h) / 2) - th))
top.geometry("%dx%d" % (w, h))
# center over the main window, not the primary screen
placeOverParent(top, parent, rely=0.5, w_width=w, w_height=h)

viewer = HTMLViewer(top, app, help_html_index)
viewer.display(doc)
Expand Down
10 changes: 10 additions & 0 deletions pysollib/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def calcCustomMouseButtonsBinding(binding_format):
dragcursor = boolean
save_games_geometry = boolean
game_geometry = int_list(min=2, max=2)
window_geometry = int_list(min=4, max=4)
topmost_dialogs = boolean
sound = boolean
sound_mode = integer(0, 1)
Expand Down Expand Up @@ -515,6 +516,7 @@ def __init__(self):
# saved games geometry (gameid: (width, height))
self.games_geometry = {}
self.game_geometry = (0, 0) # game geometry before exit
self.window_geometry = (0, 0, 0, 0)
self.offsets = {} # cards offsets
#
self.randomize_place = False
Expand Down Expand Up @@ -730,6 +732,7 @@ def save(self, filename):
for key, val in self.games_geometry.items():
config['games_geometry'][str(key)] = val
config['general']['game_geometry'] = self.game_geometry
config['general']['window_geometry'] = self.window_geometry

# offsets
for key, val in self.offsets.items():
Expand Down Expand Up @@ -928,6 +931,13 @@ def load(self, filename):
self.game_geometry = tuple(int(i) for i in game_geometry)
except Exception:
traceback.print_exc()
window_geometry = self._getOption(
'general', 'window_geometry', 'list')
if window_geometry is not None:
try:
self.window_geometry = tuple(int(i) for i in window_geometry)
except Exception:
traceback.print_exc()

# cards offsets
for key, val in config['offsets'].items():
Expand Down
9 changes: 8 additions & 1 deletion pysollib/tile/progressbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,14 @@ def __init__(self, app, parent, title=None, images=None, color="blue",
self.progress.pack(expand=True, fill='x')
self.frame.pack(expand=True, fill='both')
if 1:
setTransient(self.top, None, relx=0.5, rely=0.5)
# center over the main window (or where it will reopen)
rect = None
if parent is not None and parent.winfo_ismapped():
rect = (parent.winfo_x(), parent.winfo_y(),
parent.winfo_width(), parent.winfo_height())
elif app is not None:
rect = app.opt.window_geometry
setTransient(self.top, None, relx=0.5, rely=0.5, rect=rect)
else:
self.update(percent=0)
self.norm = norm
Expand Down
9 changes: 6 additions & 3 deletions pysollib/tile/tkwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
from pysollib.ui.tktile.tkcanvas import MfxCanvas
from pysollib.ui.tktile.tkutil import after, after_cancel, after_idle
from pysollib.ui.tktile.tkutil import bind, unbind_destroy
from pysollib.ui.tktile.tkutil import makeToplevel, setTransient
from pysollib.ui.tktile.tkutil import makeToplevel, placeOverParent
from pysollib.ui.tktile.tkutil import setTransient

# ************************************************************************
# * abstract base class for the dialogs in this module
Expand Down Expand Up @@ -89,8 +90,10 @@ def mainloop(self, focus=None, timeout=0, transient=True, geometry=""):
except SystemExit:
pass
self.destroy()
elif focus is not None:
focus.focus_set()
else:
placeOverParent(self.top, self.parent)
if focus is not None:
focus.focus_set()

def destroy(self):
after_cancel(self.timer)
Expand Down
9 changes: 8 additions & 1 deletion pysollib/tk/progressbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,14 @@ def __init__(self, app, parent, title=None, images=None, color="blue",
self.top.config(cursor="watch")
self.pack()
if 1:
setTransient(self.top, None, relx=0.5, rely=0.5)
# center over the main window (or where it will reopen)
rect = None
if parent is not None and parent.winfo_ismapped():
rect = (parent.winfo_x(), parent.winfo_y(),
parent.winfo_width(), parent.winfo_height())
elif app is not None:
rect = app.opt.window_geometry
setTransient(self.top, None, relx=0.5, rely=0.5, rect=rect)
else:
self.update(percent=0)
self.norm = norm
Expand Down
5 changes: 4 additions & 1 deletion pysollib/tk/tkwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
from pysollib.ui.tktile.tkcanvas import MfxCanvas
from pysollib.ui.tktile.tkutil import after, after_cancel
from pysollib.ui.tktile.tkutil import bind, unbind_destroy
from pysollib.ui.tktile.tkutil import makeToplevel, setTransient
from pysollib.ui.tktile.tkutil import makeToplevel, placeOverParent
from pysollib.ui.tktile.tkutil import setTransient

# ************************************************************************
# * abstract base class for the dialogs in this module
Expand Down Expand Up @@ -76,6 +77,8 @@ def mainloop(self, focus=None, timeout=0, transient=True):
except SystemExit:
pass
self.destroy()
else:
placeOverParent(self.top, self.parent)

def destroy(self):
after_cancel(self.timer)
Expand Down
2 changes: 2 additions & 0 deletions pysollib/ui/tktile/findcarddialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from pysollib.ui.tktile.tkcanvas import MfxCanvasImage, MfxCanvasRectangle
from pysollib.ui.tktile.tkutil import after, after_cancel
from pysollib.ui.tktile.tkutil import bind, makeImage, unbind_destroy
from pysollib.ui.tktile.tkutil import placeOverParent


LARGE_EMBLEMS_SIZE = (38, 34)
Expand Down Expand Up @@ -234,6 +235,7 @@ def create_find_card_dialog(parent, game, dir):
except Exception:
# traceback.print_exc()
find_card_dialog = FindCardDialog(parent, game, dir)
placeOverParent(find_card_dialog, parent)


def connect_game_find_card_dialog(game):
Expand Down
4 changes: 3 additions & 1 deletion pysollib/ui/tktile/fullpicturedialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
from pysollib.settings import TITLE
from pysollib.ui.tktile.tkcanvas import MfxCanvas, MfxCanvasGroup
from pysollib.ui.tktile.tkcanvas import MfxCanvasImage
from pysollib.ui.tktile.tkutil import bind, unbind_destroy
from pysollib.ui.tktile.tkutil import bind, placeOverParent
from pysollib.ui.tktile.tkutil import unbind_destroy


class FullPictureDialog(tkinter.Toplevel):
Expand Down Expand Up @@ -126,6 +127,7 @@ def create_full_picture_dialog(parent, game):
except Exception:
# traceback.print_exc()
full_picture_dialog = FullPictureDialog(parent, game)
placeOverParent(full_picture_dialog, parent)


def connect_game_full_picture_dialog(game):
Expand Down
4 changes: 4 additions & 0 deletions pysollib/ui/tktile/menubar.py
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,10 @@ def _createMenubar(self):
# The tk-provided menu item expects this callback.
self.top.createcommand('tk::mac::ShowHelp', self.mHelp)

if WIN_SYSTEM == "aqua":
self.top.createcommand(
'tk::mac::Quit', lambda: self.top.after_idle(self.mQuit))

menu = MfxMenu(self.menubar, label=n_("&Help"))
if WIN_SYSTEM != "aqua":
menu.add_command(
Expand Down
57 changes: 40 additions & 17 deletions pysollib/ui/tktile/tkutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,31 @@ def wm_get_geometry(window):
raise tkinter.TclError("invalid geometry "+str(g))
lst = list(map(int, m.groups()))
if window.wm_state() == "zoomed":
# workaround as Tk returns the "unzoomed" origin
lst[2] = lst[3] = 0
# Tk returns the "unzoomed" geometry; use the real one so
# this works when maximized on a secondary monitor
lst = [window.winfo_width(), window.winfo_height(),
window.winfo_x(), window.winfo_y()]
return lst


def restore_window_geometry(window, opt):
# also applied when maximized/fullscreen, so the window gets
# zoomed on the monitor it was last used on
x, y, w, h = opt.window_geometry
if w <= 0 or h <= 0:
return
try:
window.wm_geometry("%dx%d+%d+%d" % (w, h, x, y))
except tkinter.TclError:
pass


# ************************************************************************
# * window util
# ************************************************************************

def setTransient(window, parent, relx=None, rely=None, expose=1):
def setTransient(window, parent, relx=None, rely=None, expose=1,
rect=None):
# Make an existing toplevel window transient for a parent.
#
# The window must exist but should not yet have been placed; in
Expand All @@ -86,12 +101,25 @@ def setTransient(window, parent, relx=None, rely=None, expose=1):
# actualize geometry information
window.update_idletasks()
# show
x, y = __getWidgetXY(window, parent, relx=relx, rely=rely)
x, y = __getWidgetXY(window, parent, relx=relx, rely=rely, rect=rect)
window.wm_geometry("+%d+%d" % (x, y))
if expose:
window.wm_deiconify()


def placeOverParent(window, parent, relx=None, rely=None,
w_width=None, w_height=None):
# Position a non-transient window over its parent, so it opens on
# the same monitor as the main window. Stay hidden while measuring,
# so it doesn't flash at the default position first.
window.wm_withdraw()
window.update_idletasks()
x, y = __getWidgetXY(window, parent, relx=relx, rely=rely,
w_width=w_width, w_height=w_height)
window.wm_geometry("+%d+%d" % (x, y))
window.wm_deiconify()


def makeToplevel(parent, title=None):
# Create a Toplevel window.
#
Expand Down Expand Up @@ -119,7 +147,7 @@ def make_help_toplevel(app, title=None):


def __getWidgetXY(widget, parent, relx=None, rely=None,
w_width=None, w_height=None):
w_width=None, w_height=None, rect=None):
if w_width is None:
w_width = widget.winfo_reqwidth()
if w_height is None:
Expand Down Expand Up @@ -153,25 +181,20 @@ def __getWidgetXY(widget, parent, relx=None, rely=None,
relx = 0.5
if rely is None:
rely = 0.5
m_x = max(m_x, 0)
m_y = max(m_y, 0)
else:
# no mapped parent: center on the given (x, y, w, h), e.g. the
# saved main window position, instead of the primary screen
if rect and rect[2] > 0 and rect[3] > 0:
m_x, m_y, m_width, m_height = rect
if relx is None:
relx = 0.5
if rely is None:
rely = 0.3
x = m_x + int((m_width - w_width) * relx)
y = m_y + int((m_height - w_height) * rely)
# print x, y, w_width, w_height, m_x, m_y, m_width, m_height
# make sure the widget is fully on screen
if x < 0:
x = 0
elif x + w_width + 32 > s_width:
x = max(0, (s_width - w_width) // 2)
if y < 0:
y = 0
elif y + w_height + 32 > s_height:
y = max(0, (s_height - w_height) // 2)
# let's try this instead in case it ends up outside of screen
x = max(m_x, min(x, m_x + m_width - w_width))
y = max(m_y, min(y, m_y + m_height - w_height))
return x, y


Expand Down
5 changes: 4 additions & 1 deletion pysollib/winsystems/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from pysollib.settings import VERSION

if TOOLKIT == 'tk':
from pysollib.ui.tktile.tkutil import loadImage
from pysollib.ui.tktile.tkutil import loadImage, restore_window_geometry
if USE_TILE:
import tkinter.ttk as ttk

Expand Down Expand Up @@ -112,6 +112,9 @@ def base_init_root_window(root, app):
else:
root.wm_minsize(520, 360)

if TOOLKIT == 'tk':
restore_window_geometry(root, app.opt)

if TOOLKIT == 'tk' and USE_TILE:
theme = app.opt.tile_theme
init_tile(app, root)
Expand Down