def wrap_value(value):
    """Wrap a value as a Tk variable, or nested structure thereof.

    String values will automatically be stripped.
    """
    if isinstance(value, collections.Mapping):
        wrapped = wrap_dict(value)
    elif isinstance(value, list):
        wrapped = wrap_list(value)
    elif isinstance(value, str):
        wrapped = T.StringVar()
        wrapped.set(value.strip())
    elif isinstance(value, float):
        wrapped = T.DoubleVar()
        wrapped.set(value)
    elif isinstance(value, six.integer_types):
        wrapped = T.IntVar()
        wrapped.set(value)
    elif isinstance(value, bool):
        wrapped = T.BooleanVar()
        wrapped.set(value)
    elif is_tkinter_variable(value):
        # Clone the particular type of tkinter variable
        wrapped = get_tk_type(value)()
        value = value.get()
        if hasattr(value, 'strip'):
            value = value.strip()
        wrapped.set(value)
    else:
        raise ValueError('Unexpected metadata item {} of type {}'.format(
            value, type(value)))
    return wrapped
    def __init__(self, parent, title, app, **kw):
        kw = self.initKw(kw)
        MfxDialog.__init__(self, parent, title, kw.resizable, kw.default)
        top_frame, bottom_frame = self.createFrames(kw)
        # self.createBitmaps(top_frame, kw)

        frame = tkinter.Frame(top_frame)
        frame.pack(expand=True, fill='both', padx=5, pady=10)
        frame.columnconfigure(0, weight=1)

        self.demo_sleep_var = tkinter.DoubleVar()
        self.demo_sleep_var.set(app.opt.timeouts['demo'])
        self.hint_sleep_var = tkinter.DoubleVar()
        self.hint_sleep_var.set(app.opt.timeouts['hint'])
        self.raise_card_sleep_var = tkinter.DoubleVar()
        self.raise_card_sleep_var.set(app.opt.timeouts['raise_card'])
        self.highlight_piles_sleep_var = tkinter.DoubleVar()
        self.highlight_piles_sleep_var.set(app.opt.timeouts['highlight_piles'])
        self.highlight_cards_sleep_var = tkinter.DoubleVar()
        self.highlight_cards_sleep_var.set(app.opt.timeouts['highlight_cards'])
        self.highlight_samerank_sleep_var = tkinter.DoubleVar()
        self.highlight_samerank_sleep_var.set(
            app.opt.timeouts['highlight_samerank'])
        #
        # tkinter.Label(frame, text='Set delays in seconds').grid(
        #   row=0, column=0, columnspan=2)
        row = 0
        for title, var in (
            (_('Demo:'), self.demo_sleep_var),
            (_('Hint:'), self.hint_sleep_var),
            (_('Raise card:'), self.raise_card_sleep_var),
            (_('Highlight piles:'), self.highlight_piles_sleep_var),
            (_('Highlight cards:'), self.highlight_cards_sleep_var),
            (_('Highlight same rank:'), self.highlight_samerank_sleep_var),
        ):
            tkinter.Label(frame, text=title, anchor='w').grid(row=row,
                                                              column=0,
                                                              sticky='we')
            widget = tkinter.Scale(frame,
                                   from_=0.2,
                                   to=9.9,
                                   resolution=0.1,
                                   orient='horizontal',
                                   length="3i",
                                   variable=var,
                                   takefocus=0)
            widget.grid(row=row, column=1)
            row += 1
        #
        focus = self.createButtons(bottom_frame, kw)
        self.mainloop(focus, kw.timeout)
        #
        self.demo_timeout = self.demo_sleep_var.get()
        self.hint_timeout = self.hint_sleep_var.get()
        self.raise_card_timeout = self.raise_card_sleep_var.get()
        self.highlight_piles_timeout = self.highlight_piles_sleep_var.get()
        self.highlight_cards_timeout = self.highlight_cards_sleep_var.get()
        self.highlight_samerank_timeout = \
            self.highlight_samerank_sleep_var.get()
Esempio n. 3
0
    def __init__(self, minval, maxval, label_command=None,
                 side=Tk.TOP, anchor='w', master=None, **kwargs):
        self.label_command = label_command

        self.frame = Tk.Frame(master=master)
        self.frame.pack(side=side, anchor=anchor)

        self.value = Tk.DoubleVar()
        self.value.set((minval + maxval) / 2.0)
        self.scale = Tk.Scale(self.frame,
                              from_=minval, to=maxval,
                              variable=self.value,
                              orient=Tk.HORIZONTAL,
                              command=self.value_changed,
                              showvalue=False,
                              **kwargs)
        self.scale.pack(side=Tk.LEFT, anchor='w')

        if label_command is not None:
            self.label_var = Tk.StringVar()
            self.label = Tk.Label(self.frame, textvariable=self.label_var)
            self.label.pack(side=Tk.LEFT)
    def __init__(self, parent, title, app, manager, key=None, **kw):
        kw = self.initKw(kw)
        MfxDialog.__init__(self, parent, title, kw.resizable, kw.default)
        top_frame, bottom_frame = self.createFrames(kw)
        self.createBitmaps(top_frame, kw)
        #
        if key is None:
            key = manager.getSelected()
        self.manager = manager
        self.key = key
        self.app = app
        # padx, pady = kw.padx, kw.pady
        padx, pady = 5, 5
        if self.TreeDataHolder_Class.data is None:
            self.TreeDataHolder_Class.data = self.TreeData_Class(manager, key)
        #
        self.top.wm_minsize(400, 200)
        if self.top.winfo_screenwidth() >= 800:
            w1, w2 = 240, 400
        else:
            w1, w2 = 200, 300
        paned_window = tkinter.PanedWindow(top_frame)
        paned_window.pack(expand=True, fill='both')
        left_frame = tkinter.Frame(paned_window)
        right_frame = tkinter.Frame(paned_window)
        paned_window.add(left_frame)
        paned_window.add(right_frame)

        font = app.getFont("default")
        self.tree = self.Tree_Class(self,
                                    left_frame,
                                    key=key,
                                    default=kw.default,
                                    font=font,
                                    width=w1)
        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 = tkinter.Scale(
                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 = tkinter.Scale(
                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 = tkinter.Checkbutton(left_frame,
                                        text=_('Auto scaling'),
                                        variable=self.auto_scale,
                                        takefocus=False,
                                        command=self._updateAutoScale)
            check.grid(row=3,
                       column=0,
                       columnspan=2,
                       sticky='w',
                       padx=padx,
                       pady=pady)
            #
            self.preserve_aspect = tkinter.BooleanVar()
            self.preserve_aspect.set(app.opt.preserve_aspect_ratio)
            self.aspect_check = tkinter.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='w',
                                   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.setTile(app, app.tabletile_index, force=True)
        self.preview.pack(fill='both', expand=True, padx=padx, pady=pady)
        self.preview.canvas.preview = 1
        # create a preview of the current state
        self.preview_key = -1
        self.preview_images = []
        self.scale_images = []
        self.updatePreview(key)
        #
        focus = self.createButtons(bottom_frame, kw)
        focus = self.tree.frame
        self.mainloop(focus, kw.timeout)
  def __init__(self, odf, plotter):
    self.f = Figure()
    
    # Save reference to the model
    self.odf = odf
    # Save reference to the plotter
    self.plotter = plotter
    
    self.leftMask = None
    self.rightMask = None
    self.activeLine = None

    self.root = tk.Tk()
    self.root.wm_title("PyA Model Explorer")
    # Make the widgets expand/shrink as window size changes
    self.root.columnconfigure(0, weight=1)
    self.root.rowconfigure(0, weight=1)
    
    # Bind the mouse wheel
    if platform.system() == "Linux":
        self.root.bind("<Button-4>", self._mouseWheel)
        self.root.bind("<Button-5>", self._mouseWheel)    
    elif platform.system() == "Darwin":
        self.root.bind("<MouseWheel>", self._onWheel) # for OS X

    # A frame containing the mpl plot
    self.plotFrame = tk.Frame()
    self.plotFrame.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
    self.canvas = FigureCanvasTkAgg(self.f, master=self.plotFrame)
    
    # A frame containing the box with selected points
    # and control buttons
    self.controlFrame = tk.Frame(self.root)
    self.controlFrame.pack(side=tk.RIGHT, expand=False, fill=tk.BOTH)
    self.selectedPar = tk.StringVar(self.controlFrame)

    # Get parameters of model
    ps = list(self.odf.parameters().keys())
    # Set default modification properties
    # Saves these properties for all parameters
    self.modProps = {}
    for p in ps:
      self.modProps[p] = {"modus":"mul", "modValMul":1.02, "modValAdd":0.01}
    
    # Frame containing all parameters
    self.parameterFrame = tk.Frame(self.controlFrame, height=2, bd=1, relief=tk.SUNKEN)    
    
    # Dictionaries holding the specific information for each parameter
    self.singleParameterFrames = {}
    self.singleParameterEntry = {}
    self.singleParameterVar = {}
    self.singleParameterFree = {} # knows whether the parameter is free (value=True) or frozen (=False)
        
    # Closures around the functions adapting thaw/freeze    
    def frozenChanged(k):
        def change():
            if self.singleParameterFree[k].get() == True:
                self.odf.thaw(k)
            else:
                self.odf.freeze(k)
            self._updateDof()     
        return change
    
    # define what happens when a value is set to the entered parameter (closures)
    def hitReturn(k):
      def change(*args):
        self.selectedPar.set(k)
        self.odf[k] = float(self.singleParameterVar[k].get())
        self._parameterValueChanged()
      return change  
    
    # defines what happens when a parameter's value is changed, but not set yet, i.e., not current (closures)
    def parameterValueChanged(k):
        def valueChanged(*args):
            pp,ll = str(self.singleParameterVar[k].get()).find("."), len(str(self.singleParameterVar[k].get()))
            if round(self.odf[k],ll-pp-1) != round(self.singleParameterVar[k].get(), ll-pp-1):
                self.singleParameterEntry[k].configure(bg = "red")
            else:
                self.singleParameterEntry[k].configure(bg = "white")
        return valueChanged    
    
    
    # Create an entry for each parameter
      ## Create a scrollable region
      ## Check maximum number of characters for parameter names:
    maxParamLen = 0
    for k in sorted(self.odf.parameters().keys()):
      if len(k) > maxParamLen:
        maxParamLen = len(k)
      ## Create an entry for each parameter	
    for k in sorted(self.odf.parameters().keys()):
      x = tk.Frame(self.parameterFrame, height=2, bd=2, relief=tk.SUNKEN,pady=2)
      self.singleParameterFrames[k] = x 
      y0 = tk.Radiobutton(x, text=k,variable=self.selectedPar,value=k, width=maxParamLen+1, indicatoron=0)
      y0.pack(side=tk.LEFT)
      #y1 = tk.StringVar()
      y1 = tk.DoubleVar()
      y1.set(self.odf[k])
      y2 = tk.Entry(x, textvariable=y1, width=8)
      y2.bind('<Return>', hitReturn(k))
      self.singleParameterVar[k] = y1
      self.singleParameterVar[k].trace('w', parameterValueChanged(k))
      self.singleParameterEntry[k]= y2
      y2.pack(side=tk.LEFT)
      self.singleParameterFrames[k].pack()
      modModus = tk.StringVar()
      modModus.set(self.modProps[k]["modus"])
      self.singleParameterFree[k] = tk.BooleanVar()
      self.singleParameterFree[k].set(k in self.odf.freeParamNames())
      y3 = tk.Radiobutton(x, text="Thawed", value=True,variable=self.singleParameterFree[k], command=frozenChanged(k))
      y4 = tk.Radiobutton(x, text="Frozen", value=False,variable=self.singleParameterFree[k], command=frozenChanged(k))
      y3.pack(side=tk.RIGHT)
      y4.pack(side=tk.RIGHT)
      self.parameterFrame.pack(fill=tk.X, expand=False)
      
    # Set of the menu to select the current parameter
    self.selectedPar.set(ps[0])
    
    
    # Chi2 frame:
    self.chi2Frame = tk.Frame(self.controlFrame, borderwidth=10)#, relief=tk.SUNKEN)
    self.chi2value = tk.DoubleVar()
    self.chi2value.set(self.plotter.chi2)
    self.dofValue = tk.IntVar()
    #self.dofValue.set(len(self.plotter.fitIdx))
    #self.dofValue.set(100)
    self.dofValue.set(len(self.plotter.x) - len(self.odf.freeParameters())-1)
    self.chi2Label = tk.Label(self.chi2Frame,text="Chi2: ")
    self.dofLabel = tk.Label(self.chi2Frame,text="dof: ")
    self.chi2Entry = tk.Entry(self.chi2Frame, textvariable=self.chi2value, bd=2, width=10)
    self.dofEntry = tk.Entry(self.chi2Frame, textvariable=self.dofValue, bd=2, width=10)
    self.chi2Label.pack(side=tk.LEFT)
    self.chi2Entry.pack(side=tk.LEFT)
    self.dofLabel.pack(side=tk.LEFT)
    self.dofEntry.pack(side=tk.LEFT)
    self.chi2Frame.pack()
  
    
    # Frame to bundle mouse-wheel inputs
    self.mouseWheelFrame = tk.Frame(self.controlFrame, height=2, bd=3, relief=tk.SUNKEN)
    self.mwmLabel = tk.Label(self.mouseWheelFrame, text="Mouse wheel manipulation")
    self.mwmLabel.pack()
    # Modify by multiplication or addition (modModus)
    self.modModus = tk.StringVar()
    self.modModus.set("mul")
    # Entry field and radiobutton to specify factor to be used
    self.factorFrame = tk.Frame(self.mouseWheelFrame)
    self.modEntryTextMul = tk.StringVar()
    self.modEntryFactor = tk.Entry(self.factorFrame, textvariable=self.modEntryTextMul, width=6)
    self.modEntryFactor.pack(side=tk.LEFT)
    self.radioMultipli = tk.Radiobutton(self.factorFrame, text="Multiply", value="mul", variable=self.modModus)
    self.radioMultipli.pack(side=tk.LEFT)
    self.factorFrame.pack(fill=tk.BOTH)
    # Entry field and radiobutton to specify step (delta) to be used
    self.addFrame = tk.Frame(self.mouseWheelFrame)
    self.modEntryTextAdd = tk.StringVar()
    self.modEntryAdd = tk.Entry(self.addFrame, textvariable=self.modEntryTextAdd, width=6)
    self.modEntryAdd.pack(side=tk.LEFT)
    self.radioAdd = tk.Radiobutton(self.addFrame, text="Add", value="add", variable=self.modModus)
    self.radioAdd.pack(side=tk.LEFT)
    self.addFrame.pack(fill=tk.BOTH)
    # Set text fields for modification factor/step to default
    self.modEntryTextMul.set(self.modProps[self.selectedPar.get()]["modValMul"])
    self.modEntryTextAdd.set(self.modProps[self.selectedPar.get()]["modValAdd"])
    self.modEntryTextAdd.trace("w", self._modModeChangedAdd)
    self.modEntryTextMul.trace("w", self._modModeChangedMul)
    # Show the frame
#     self.mouseWheelFrame.grid(row=4, column=0, columnspan=3, pady=10)
    self.mouseWheelFrame.pack()
    
    
    # React to change in modify Modus
    self.modModus.trace('w', self._modModusChanged)
    # React to a change in the active parameter
    self.selectedPar.trace("w", self._activeParameterChanged)
    
    dummyLabel = tk.Label(self.controlFrame)
    dummyLabel.pack()
    
    # Fit button and fit ranges
    self.fitRangeFrame = tk.Frame(self.controlFrame, bd=3, relief=tk.SUNKEN)
    self.fit_lo = tk.DoubleVar()
    self.fit_hi = tk.DoubleVar()
    self.fit_lo.set(min(plotter.x))
    self.fit_hi.set(max(plotter.x))
    self.fitRangeLoLim = tk.Entry(self.fitRangeFrame, textvariable=self.fit_lo, width=9, bd=2)
    self.fitRangeHiLim = tk.Entry(self.fitRangeFrame, textvariable=self.fit_hi, width=9, bd=2)
    self.fitRangeLabel = tk.Label(self.fitRangeFrame, text="Fit range:")
    self.fitButton = tk.Button(self.fitRangeFrame, text="Fit", command=self._fitClicked)
    self.fitButton.pack(side=tk.BOTTOM, fill=tk.X)
    self.fitRangeLabel.pack(side=tk.LEFT, fill=tk.X)
    self.fitRangeHiLim.pack(side=tk.RIGHT)    
    self.fitRangeLoLim.pack(side=tk.RIGHT)
    self.fitRangeFrame.pack(fill=tk.X)
    #self.fitRangeLoLim.bind('<Return>', self._fitRangeChanged())
    self.fit_lo.trace("w", self._fitRangeChanged)
    self.fit_hi.trace("w", self._fitRangeChanged)
    self.numberClicked=0
    #self.modModus.trace('w', self._modModusChanged)
    #self.modModus.trace('w', self._modModusChanged)
    
    dummyLabel = tk.Label(self.controlFrame)
    dummyLabel.pack()
    
    self.showFrame = tk.Frame(self.controlFrame, bd=3)#, relief=tk.SUNKEN)
    self.showFrame.pack(side=tk.TOP)
    
    self.parSumButton = tk.Button(self.showFrame, text="Parameter summary", command=self._parameterSummaryClicked)
    self.parSumButton.pack(side=tk.LEFT)
        
    self.valSetButton = tk.Button(self.showFrame, text="Value set code", command=self._valueSetClicked)
#     self.valSetButton.grid(row=7, column=2)
    self.valSetButton.pack(side=tk.RIGHT)
     
    # a tk.DrawingArea
#     self.canvas.get_tk_widget().grid(column=0, columnspan=7, row=0, rowspan=10)
    self.canvas.get_tk_widget().pack()
    self.cid = self.f.canvas.mpl_connect('button_press_event', self._mouseButtonClicked)
    self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.plotFrame)
    self.toolbar.update()
    self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

    def _quit():
      # stops main loop
      self.root.quit()
      # this is necessary on Windows to prevent
      # Fatal Python Error: PyEval_RestoreThread: NULL tstate
      self.root.destroy()

    self.quitButton = tk.Button(master=self.controlFrame, text='Quit', command=_quit)
    self.quitButton.pack(side=tk.BOTTOM)
    
    # Plot the model for the first time
    self._parameterValueChanged()
    
    # Whether or not parameter summary exists
    self.root.parSumWin = None
    
    if platform.system() == "Darwin":
        self.root.bind("<MouseWheel>", self._onWheel) # for OS X
Esempio n. 6
0
    def __init__(self, parent, title, app, manager, key=None, **kw):
        kw = self.initKw(kw)
        MfxDialog.__init__(self, parent, title, kw.resizable, kw.default)
        top_frame, bottom_frame = self.createFrames(kw)
        self.createBitmaps(top_frame, kw)
        #
        if key is None:
            key = manager.getSelected()
        self.manager = manager
        self.key = key
        self.app = app
        self.cardset_values = None
        # padx, pady = kw.padx, kw.pady
        padx, pady = 4, 4
        if self.TreeDataHolder_Class.data is None:
            self.TreeDataHolder_Class.data = self.TreeData_Class(manager, key)
        #
        sw = self.top.winfo_screenwidth()
        sh = self.top.winfo_screenheight()

        h = int(sh * .8)
        w = int(sw * .8)
        w1 = int(min(275, sw / 2.5))
        geometry = ("%dx%d+%d+%d" % (w, h, (sw - w) / 2, (sh - h) / 2))
        self.top.wm_minsize(400, 200)

        paned_window = ttk.PanedWindow(top_frame, orient='horizontal')
        paned_window.pack(expand=True, fill='both', padx=8, pady=8)
        left_frame = ttk.Frame(paned_window)
        right_frame = ttk.Frame(paned_window)
        paned_window.add(left_frame)
        paned_window.add(right_frame)

        notebook = ttk.Notebook(left_frame)
        notebook.grid(row=0, column=0, sticky='nsew', padx=padx, pady=pady)
        tree_frame = ttk.Frame(notebook)
        notebook.add(tree_frame, text=_('Tree View'))
        search_frame = ttk.Frame(notebook)
        notebook.add(search_frame, text=_('Search'))

        # Tree
        font = app.getFont("default")
        self.tree = self.Tree_Class(self,
                                    tree_frame,
                                    key=key,
                                    default=kw.default,
                                    font=font,
                                    width=w1)
        self.tree.frame.pack(padx=padx, pady=pady, expand=True, fill='both')

        # Search
        searchText = tkinter.StringVar()
        self.list_searchlabel = tkinter.Label(search_frame,
                                              text="Search:",
                                              justify='left',
                                              anchor='w')
        self.list_searchlabel.pack(side="top", fill='both', ipadx=1)
        self.list_searchtext = tkinter.Entry(search_frame,
                                             textvariable=searchText)
        self.list_searchtext.pack(side="top",
                                  fill='both',
                                  padx=padx,
                                  pady=pady,
                                  ipadx=1)
        searchText.trace('w', self.performSearch)

        self.list_scrollbar = tkinter.Scrollbar(search_frame)
        self.list_scrollbar.pack(side="right", fill='both')

        self.createBitmaps(search_frame, kw)
        self.list = tkinter.Listbox(search_frame, exportselection=False)
        self.list.pack(padx=padx,
                       pady=pady,
                       expand=True,
                       side='left',
                       fill='both',
                       ipadx=1)
        self.updateSearchList("")
        bind(self.list, '<<ListboxSelect>>', self.selectSearchResult)
        bind(self.list, '<FocusOut>',
             lambda e: self.list.selection_clear(0, 'end'))

        self.list.config(yscrollcommand=self.list_scrollbar.set)
        self.list_scrollbar.config(command=self.list.yview)

        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)
            #
            # sliders at new position
            cs = self.manager.get(self.tree.selection_key)

            var = tkinter.IntVar()
            self.x_offset = PysolScale(left_frame,
                                       label=_('X offset:'),
                                       from_=5,
                                       to=100,
                                       resolution=1,
                                       orient='horizontal',
                                       variable=var,
                                       value=cs.CARD_XOFFSET)

            self.x_offset.grid(row=3,
                               column=0,
                               sticky='ew',
                               padx=padx,
                               pady=pady)

            var = tkinter.IntVar()
            self.y_offset = PysolScale(left_frame,
                                       label=_('Y offset:'),
                                       from_=5,
                                       to=100,
                                       resolution=1,
                                       orient='horizontal',
                                       variable=var,
                                       value=cs.CARD_YOFFSET)
            self.y_offset.grid(row=4,
                               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=5,
                       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=6,
                                   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)
        self.preview.setTile(app, app.tabletile_index, force=True)
        self.preview.pack(fill='both', expand=True, padx=padx, pady=pady)
        self.preview.canvas.preview = 1
        # create a preview of the current state
        self.preview_key = -1
        self.preview_images = []
        self.scale_images = []
        self.updatePreview(key)
        #
        focus = self.createButtons(bottom_frame, kw)
        focus = self.tree.frame
        self.mainloop(focus, kw.timeout, geometry=geometry)