Package nMOLDYN :: Package GUI :: Package HTMLReader :: Module tkutil |
[hide private]
[frames] | no frames]

# Source Code for Module nMOLDYN.GUI.HTMLReader.tkutil

      1  ## vim:ts=4:et:nowrap
      2  ##
      3  ##---------------------------------------------------------------------------##
      4  ##
      5  ## PySol -- a Python Solitaire game
      6  ##
      7  ## Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
      8  ## Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
      9  ## Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
     10  ## Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
     11  ## Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
     12  ## Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
     13  ## All Rights Reserved.
     14  ##
     15  ## This program is free software; you can redistribute it and/or modify
     16  ## it under the terms of the GNU General Public License as published by
     17  ## the Free Software Foundation; either version 2 of the License, or
     18  ## (at your option) any later version.
     19  ##
     20  ## This program is distributed in the hope that it will be useful,
     21  ## but WITHOUT ANY WARRANTY; without even the implied warranty of
     22  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     23  ## GNU General Public License for more details.
     24  ##
     25  ## You should have received a copy of the GNU General Public License
     26  ## along with this program; see the file COPYING.
     27  ## If not, write to the Free Software Foundation, Inc.,
     28  ## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     29  ##
     30  ## Markus F.X.J. Oberhumer
     31  ## <markus@oberhumer.com>
     32  ## http://www.oberhumer.com/pysol
     33  ##
     34  ##---------------------------------------------------------------------------##
     35
     36
     37  # imports
     38  import sys, os, re, string, time, types
     39  import Tkinter
     40
     41  # Toolkit imports
     42  import tkinit
     43  from tkconst import tkversion
     44  from tkfont import getFont
     45
     46
     47  # /***********************************************************************
     48  # // window manager util
     49  # ************************************************************************/
     50
     51 -def wm_withdraw(window):
     52      window.wm_withdraw()
     53
     54 -def wm_deiconify(window):
     55      need_fix = os.name == "nt" and tkversion < (8, 3, 0, 0)
     56      if need_fix:
     57          # FIXME: This is needed so the window pops up on top on Windows.
     58          try:
     59              window.wm_iconify()
     60              window.update_idletasks()
     61          except Tkinter.TclError:
     62              # wm_iconify() may fail if the window is transient
     63              pass
     64      window.wm_deiconify()
     65
     66 -def wm_map(window, maximized=0):
     67      if window.wm_state() != "iconic":
     68          if maximized and os.name == "nt":
     69              window.wm_state("zoomed")
     70          else:
     71              wm_deiconify(window)
     72
     73 -def wm_set_icon(window, filename):
     74      if not filename:
     75          return
     76      if os.name == "posix":
     77          window.wm_iconbitmap("@" + filename)
     78          window.wm_iconmask("@" + filename)
     79
     80  __wm_get_geometry_re = re.compile(r"^(\d+)x(\d+)\+([\-]?\d+)\+([\-]?\d+)$")
     81
     82 -def wm_get_geometry(window):
     83      g = window.wm_geometry()
     84      m = __wm_get_geometry_re.search(g)
     85      if not m:
     86          raise Tkinter.TclError, "invalid geometry " + str(g)
     87      l = map(int, m.groups())
     88      if window.wm_state() == "zoomed":
     89          # workaround as Tk returns the "unzoomed" origin
     90          l[2] = l[3] = 0
     91      return l
     92
     93
     94  # /***********************************************************************
     95  # // window util
     96  # ************************************************************************/
     97
     98 -def setTransient(window, parent, relx=None, rely=None, expose=1):
     99      # Make an existing toplevel window transient for a parent.
    100      #
    101      # The window must exist but should not yet have been placed; in
    102      # other words, this should be called after creating all the
    103      # subwidget but before letting the user interact.
    104
    105      # remain invisible while we figure out the geometry
    106      window.wm_withdraw()
    107      window.wm_group(parent)
    108      need_fix = os.name == "nt" and tkversion < (8, 3, 0, 0)
    109      if need_fix:
    110          # FIXME: This is needed to avoid ugly frames on Windows.
    111          window.wm_geometry("+%d+%d" % (-10000, -10000))
    112          if expose and parent is not None:
    113              # FIXME: This is needed so the window pops up on top on Windows.
    114              window.wm_iconify()
    115      if parent and parent.wm_state() != "withdrawn":
    116          window.wm_transient(parent)
    117      # actualize geometry information
    118      window.update_idletasks()
    119      # show
    120      x, y = __getWidgetXY(window, parent, relx=relx, rely=rely)
    121      if need_fix:
    122          if expose:
    123              wm_deiconify(window)
    124          window.wm_geometry("+%d+%d" % (x, y))
    125      else:
    126          window.wm_geometry("+%d+%d" % (x, y))
    127          if expose:
    128              window.wm_deiconify()
    129
    130 -def makeToplevel(parent, title=None, class_=None):
    131      # Create a Toplevel window.
    132      #
    133      # This is a shortcut for a Toplevel() instantiation plus calls to
    134      # set the title and icon name of the window.
    135      if class_:
    136          window = Tkinter.Toplevel(parent, class_=class_)
    137      else:
    138          window = Tkinter.Toplevel(parent)
    139      ##window.wm_group(parent)
    140      ##window.wm_command("")
    141      if os.name == "posix":
    142          window.wm_command("/bin/true")
    143      ##window.wm_protocol("WM_SAVE_YOURSELF", None)
    144      if title:
    145          window.wm_title(title)
    146          window.wm_iconname(title)
    147      return window
    148
    149  makeHelpToplevel = makeToplevel
    150
    151 -def __getWidgetXY(widget, parent, relx=None, rely=None,
    152                    w_width=None, w_height=None):
    153      if w_width is None:
    154          w_width = widget.winfo_reqwidth()
    155      if w_height is None:
    156          w_height = widget.winfo_reqheight()
    157      s_width = widget.winfo_screenwidth()
    158      s_height = widget.winfo_screenheight()
    159      m_x = m_y = 0
    160      m_width, m_height = s_width, s_height
    161      if parent and parent.winfo_ismapped():
    162          ##print parent.wm_geometry()
    163          ##print parent.winfo_geometry(), parent.winfo_x(), parent.winfo_y(), parent.winfo_rootx(), parent.winfo_rooty(), parent.winfo_vrootx(), parent.winfo_vrooty()
    164          m_x = m_y = None
    165          if os.name == "nt":
    166              try:
    167                  m_width, m_height, m_x, m_y = wm_get_geometry(parent)
    168              except:
    169                  pass
    170          if m_x is None:
    171              m_x = parent.winfo_x()
    172              m_y = parent.winfo_y()
    173              m_width = parent.winfo_width()
    174              m_height = parent.winfo_height()
    175              if relx is None: relx = 0.5
    176              if rely is None: rely = 0.3
    177          else:
    178              if relx is None: relx = 0.5
    179              if rely is None: rely = 0.5
    180          m_x = max(m_x, 0)
    181          m_y = max(m_y, 0)
    182      else:
    183          if relx is None: relx = 0.5
    184          if rely is None: rely = 0.3
    185      x = m_x + int((m_width - w_width) * relx)
    186      y = m_y + int((m_height - w_height) * rely)
    187      ##print x, y, w_width, w_height, m_x, m_y, m_width, m_height
    188      # make sure the widget is fully on screen
    189      if x < 0: x = 0
    190      elif x + w_width + 32 > s_width: x = max(0, (s_width - w_width) / 2)
    191      if y < 0: y = 0
    192      elif y + w_height + 32 > s_height: y = max(0, (s_height - w_height) / 2)
    193      return x, y
    194
    195
    196  # /***********************************************************************
    197  # // bind wrapper - Tkinter doesn't properly delete all bindings
    198  # ************************************************************************/
    199
    200  __mfx_bindings = {}
    201  __mfx_wm_protocols = ("WM_DELETE_WINDOW", "WM_TAKE_FOCUS", "WM_SAVE_YOURSELF")
    202
    203 -def bind(widget, sequence, func, add=None):
    204      assert callable(func)
    205      if sequence in __mfx_wm_protocols:
    206          funcid = widget._register(func)
    207          widget.tk.call("wm", "protocol", widget._w, sequence, funcid)
    208      elif add is None:
    209          funcid = widget.bind(sequence, func)
    210      else:
    211          ##add = add and "+" or ""
    212          funcid = widget.bind(sequence, func, add)
    213      k = id(widget)
    214      if __mfx_bindings.has_key(k):
    215          __mfx_bindings[k].append((sequence, funcid))
    216      else:
    217          __mfx_bindings[k] = [(sequence, funcid)]
    218
    219 -def unbind_destroy(widget):
    220      if widget is None:
    221          return
    222      k = id(widget)
    223      if __mfx_bindings.has_key(k):
    224          for sequence, funcid in __mfx_bindings[k]:
    225              ##print widget, sequence, funcid
    226              try:
    227                  if sequence in __mfx_wm_protocols:
    228                      widget.tk.call("wm", "protocol", widget._w, sequence, "")
    229                      ##widget.deletecommand(funcid)
    230                  else:
    231                      widget.unbind(sequence, funcid)
    232              except Tkinter.TclError:
    233                  pass
    234          del __mfx_bindings[k]
    235      ##for k in __mfx_bindings.keys(): print __mfx_bindings[k]
    236      ##print len(__mfx_bindings.keys())
    237
    238
    239  # /***********************************************************************
    240  # // timer wrapper - Tkinter doesn't properly delete all commands
    241  # ************************************************************************/
    242
    243 -def after(widget, ms, func, *args):
    244      timer = apply(widget.after, (ms, func) + args)
    245      command = widget._tclCommands[-1]
    246      return (timer, command, widget)
    247
    248 -def after_idle(widget, func, *args):
    249      return apply(after, (widget, "idle", func) + args)
    250
    251 -def after_cancel(t):
    252      if t is not None:
    253          t[2].after_cancel(t[0])
    254          try:
    255              t[2].deletecommand(t[1])
    256          except Tkinter.TclError:
    257              pass
    258
    259
    260  # /***********************************************************************
    261  # // image handling
    262  # ************************************************************************/
    263
    264 -def makeImage(file=None, data=None, dither=None, alpha=None):
    265      kw = {}
    266      if data is None:
    267          assert file is not None
    268          kw["file"] = file
    269      else:
    270          assert data is not None
    271          kw["data"] = data
    272      if os.name == "nt":
    273          if dither is not None:
    274              kw["dither"] = dither
    275          if alpha is not None:
    276              kw["alpha"] = alpha
    277      return apply(Tkinter.PhotoImage, (), kw)
    278
    279  loadImage = makeImage
    280
    281 -def copyImage(image, x, y, width, height):
    282      dest = Tkinter.PhotoImage(width=width, height=height)
    283      assert dest.width() == width
    284      assert dest.height() == height
    285      dest.blank()
    286      image.tk.call(dest, "copy", image.name, "-from", x, y, x+width, y+height)
    287      assert dest.width() == width
    288      assert dest.height() == height
    289      return dest
    290
    291 -def fillImage(image, fill, outline=None):
    292      if not fill and not outline:
    293          return
    294      width = image.width()
    295      height = image.height()
    296      ow = 1                              # outline width
    297      if width <= 2*ow or height <= 2*ow:
    298          fill = fill or outline
    299          outline = None
    300      if not outline:
    301          f = (fill,) * width
    302          f = (f,) * height
    303          assert len(f) == height
    304          image.put(f)
    305      elif not fill:
    306          l = ((outline,) * width,)
    307          for y in range(0, ow):
    308              image.put(l, (0, y))
    309          for y in range(height-ow, height):
    310              image.put(l, (0, y))
    311          p = ((outline,) * ow,)
    312          for y in range(ow, height-ow):
    313              image.put(p, (0, y))
    314              image.put(p, (width-ow, y))
    315      else:
    316          l1 = (outline,) * width
    317          l2 = (outline,) * ow + (fill,) * (width-2*ow) + (outline,) * ow
    318          f = (l1,) * ow + (l2,) * (height-2*ow) + (l1,) * ow
    319          assert len(f) == height
    320          image.put(f)
    321
    322 -def createImage(width, height, fill, outline=None):
    323      image = Tkinter.PhotoImage(width=width, height=height)
    324      assert image.width() == width
    325      assert image.height() == height
    326      image.blank()
    327      fillImage(image, fill, outline)
    328      return image
    329