1#!/usr/bin/env python
2# -*- mode: python; coding: utf-8; -*-
3# ---------------------------------------------------------------------------
4#
5# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
6# Copyright (C) 2003 Mt. Hood Playing Card Co.
7# Copyright (C) 2005-2009 Skomoroh
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program.  If not, see <http://www.gnu.org/licenses/>.
21#
22# ---------------------------------------------------------------------------
23
24from pysollib.mfxutil import KwStruct
25from pysollib.mygettext import _
26from pysollib.ui.tktile.tkutil import bind
27
28from six.moves import tkinter
29from six.moves import tkinter_font
30from six.moves import tkinter_ttk as ttk
31
32from .tkwidget import MfxDialog
33from .tkwidget import PysolScale
34
35
36# ************************************************************************
37# *
38# ************************************************************************
39
40class FontChooserDialog(MfxDialog):
41    def __init__(self, parent, title, init_font, **kw):
42        # print init_font
43        kw = self.initKw(kw)
44        MfxDialog.__init__(self, parent, title, kw.resizable, kw.default)
45        top_frame, bottom_frame = self.createFrames(kw)
46        self.createBitmaps(top_frame, kw)
47
48        self.font_family = 'Helvetica'
49        self.font_size = 12
50        self.font_weight = 'normal'
51        self.font_slant = 'roman'
52
53        if init_font is not None:
54            assert 2 <= len(init_font) <= 4
55            assert isinstance(init_font[1], int)
56            self.font_family, self.font_size = init_font[:2]
57            if len(init_font) > 2:
58                if init_font[2] in ['bold', 'normal']:
59                    self.font_weight = init_font[2]
60                elif init_font[2] in ['italic', 'roman']:
61                    self.font_slant = init_font[2]
62                else:
63                    raise ValueError('invalid font style: '+init_font[2])
64                if len(init_font) > 3:
65                    if init_font[3] in ['bold', 'normal']:
66                        self.font_weight = init_font[3]
67                    elif init_font[2] in ['italic', 'roman']:
68                        self.font_slant = init_font[3]
69                    else:
70                        raise ValueError('invalid font style: '+init_font[3])
71
72        # self.family_var = tkinter.StringVar()
73        self.weight_var = tkinter.BooleanVar()
74        self.weight_var.set(self.font_weight == 'bold')
75        self.slant_var = tkinter.BooleanVar()
76        self.slant_var.set(self.font_slant == 'italic')
77        self.size_var = tkinter.IntVar()
78        self.size_var.set(self.font_size)
79        #
80        frame = ttk.Frame(top_frame)
81        frame.pack(expand=True, fill='both', padx=5, pady=10)
82        frame.columnconfigure(0, weight=1)
83        # frame.rowconfigure(1, weight=1)
84        self.entry = ttk.Entry(frame)
85        self.entry.grid(row=0, column=0, columnspan=2, sticky='news')
86        self.entry.insert('end', _('abcdefghABCDEFGH'))
87        self.list_box = tkinter.Listbox(frame, width=36, exportselection=False)
88        sb = ttk.Scrollbar(frame)
89        self.list_box.configure(yscrollcommand=sb.set)
90        sb.configure(command=self.list_box.yview)
91        self.list_box.grid(row=1, column=0, sticky='news')  # rowspan=4
92        sb.grid(row=1, column=1, sticky='ns')
93        bind(self.list_box, '<<ListboxSelect>>', self.fontupdate)
94        # self.list_box.focus()
95        cb1 = ttk.Checkbutton(frame, text=_('Bold'),
96                              command=self.fontupdate,
97                              variable=self.weight_var)
98        cb1.grid(row=2, column=0, columnspan=2, sticky='we')
99        cb2 = ttk.Checkbutton(frame, text=_('Italic'),
100                              command=self.fontupdate,
101                              variable=self.slant_var)
102        cb2.grid(row=3, column=0, columnspan=2, sticky='we')
103
104        sc = PysolScale(frame, from_=6, to=40, resolution=1,
105                        label=_('Size:'), orient='horizontal',
106                        command=self.fontupdate, variable=self.size_var)
107        sc.grid(row=4, column=0, columnspan=2, sticky='news')
108        #
109        font_families = list(tkinter_font.families())
110        font_families.sort()
111        selected = -1
112        n = 0
113        self.list_box.insert('end', *font_families)
114        for font in font_families:
115            if font.lower() == self.font_family.lower():
116                selected = n
117                break
118            n += 1
119        if selected >= 0:
120            self.list_box.select_set(selected)
121            self.list_box.see(selected)
122        #
123        focus = self.createButtons(bottom_frame, kw)
124        self.mainloop(focus, kw.timeout)
125
126        self.font = (self.font_family, self.font_size,
127                     self.font_slant, self.font_weight)
128
129    def fontupdate(self, *args):
130        if self.list_box.curselection():
131            self.font_family = self.list_box.get(self.list_box.curselection())
132        self.font_weight = self.weight_var.get() and 'bold' or 'normal'
133        self.font_slant = self.slant_var.get() and 'italic' or 'roman'
134        self.font_size = self.size_var.get()
135        self.entry.configure(font=(self.font_family, self.font_size,
136                                   self.font_slant, self.font_weight))
137
138    def initKw(self, kw):
139        kw = KwStruct(kw,
140                      strings=(_("&OK"), _("&Cancel")),
141                      default=0,
142                      )
143        return MfxDialog.initKw(self, kw)
144
145# ************************************************************************
146# *
147# ************************************************************************
148
149
150class FontsDialog(MfxDialog):
151    def __init__(self, parent, title, app, **kw):
152        kw = self.initKw(kw)
153        MfxDialog.__init__(self, parent, title, kw.resizable, kw.default)
154        top_frame, bottom_frame = self.createFrames(kw)
155        self.createBitmaps(top_frame, kw)
156
157        frame = ttk.Frame(top_frame)
158        frame.pack(expand=True, fill='both', padx=5, pady=10)
159        frame.columnconfigure(0, weight=1)
160
161        self.fonts = {}
162        row = 0
163        for fn, title in (  # ('default',        _('Default')),
164                          ('sans',           _('HTML: ')),
165                          ('small',          _('Small: ')),
166                          ('fixed',          _('Fixed: ')),
167                          ('canvas_default', _('Tableau default: ')),
168                          ('canvas_fixed',   _('Tableau fixed: ')),
169                          ('canvas_large',   _('Tableau large: ')),
170                          ('canvas_small',   _('Tableau small: ')),
171                          ):
172            font = app.opt.fonts[fn]
173            self.fonts[fn] = font
174            ttk.Label(frame, text=title, anchor='w'
175                      ).grid(row=row, column=0, sticky='we')
176            if font:
177                title = ' '.join(
178                    [str(i) for i in font if i not in ('roman', 'normal')])
179            elif font is None:
180                title = 'Default'
181            label = ttk.Label(frame, font=font, text=title)
182            label.grid(row=row, column=1, padx=8)
183            b = ttk.Button(frame, text=_('Change...'), width=10,
184                           command=lambda label=label,
185                           fn=fn: self.selectFont(label, fn))
186            b.grid(row=row, column=2)
187            row += 1
188        #
189        focus = self.createButtons(bottom_frame, kw)
190        self.mainloop(focus, kw.timeout)
191
192    def selectFont(self, label, fn):
193        d = FontChooserDialog(self.top, _('Select font'), self.fonts[fn])
194        if d.status == 0 and d.button == 0:
195            self.fonts[fn] = d.font
196            title = ' '.join(
197                [str(i) for i in d.font if i not in ('roman', 'normal')])
198            label.configure(font=d.font, text=title)
199
200    def initKw(self, kw):
201        kw = KwStruct(kw,
202                      strings=(_('&OK'), _('&Cancel')),
203                      default=0,
204                      )
205        return MfxDialog.initKw(self, kw)
206