1"""TextViewer class.
2
3The TextViewer allows you to see how the selected color would affect various
4characteristics of a Tk text widget.  This is an output viewer only.
5
6In the top part of the window is a standard text widget with some sample text
7in it.  You are free to edit this text in any way you want (BAW: allow you to
8change font characteristics).  If you want changes in other viewers to update
9text characteristics, turn on Track color changes.
10
11To select which characteristic tracks the change, select one of the radio
12buttons in the window below.  Text foreground and background affect the text
13in the window above.  The Selection is what you see when you click the middle
14button and drag it through some text.  The Insertion is the insertion cursor
15in the text window (which only has a background).
16"""
17
18from Tkinter import *
19import ColorDB
20
21ADDTOVIEW = 'Text Window...'
22
23
24
25class TextViewer:
26    def __init__(self, switchboard, master=None):
27        self.__sb = switchboard
28        optiondb = switchboard.optiondb()
29        root = self.__root = Toplevel(master, class_='Pynche')
30        root.protocol('WM_DELETE_WINDOW', self.withdraw)
31        root.title('Pynche Text Window')
32        root.iconname('Pynche Text Window')
33        root.bind('<Alt-q>', self.__quit)
34        root.bind('<Alt-Q>', self.__quit)
35        root.bind('<Alt-w>', self.withdraw)
36        root.bind('<Alt-W>', self.withdraw)
37        #
38        # create the text widget
39        #
40        self.__text = Text(root, relief=SUNKEN,
41                           background=optiondb.get('TEXTBG', 'black'),
42                           foreground=optiondb.get('TEXTFG', 'white'),
43                           width=35, height=15)
44        sfg = optiondb.get('TEXT_SFG')
45        if sfg:
46            self.__text.configure(selectforeground=sfg)
47        sbg = optiondb.get('TEXT_SBG')
48        if sbg:
49            self.__text.configure(selectbackground=sbg)
50        ibg = optiondb.get('TEXT_IBG')
51        if ibg:
52            self.__text.configure(insertbackground=ibg)
53        self.__text.pack()
54        self.__text.insert(0.0, optiondb.get('TEXT', '''\
55Insert some stuff here and play
56with the buttons below to see
57how the colors interact in
58textual displays.
59
60See how the selection can also
61be affected by tickling the buttons
62and choosing a color.'''))
63        insert = optiondb.get('TEXTINS')
64        if insert:
65            self.__text.mark_set(INSERT, insert)
66        try:
67            start, end = optiondb.get('TEXTSEL', (6.0, END))
68            self.__text.tag_add(SEL, start, end)
69        except ValueError:
70            # selection wasn't set
71            pass
72        self.__text.focus_set()
73        #
74        # variables
75        self.__trackp = BooleanVar()
76        self.__trackp.set(optiondb.get('TRACKP', 0))
77        self.__which = IntVar()
78        self.__which.set(optiondb.get('WHICH', 0))
79        #
80        # track toggle
81        self.__t = Checkbutton(root, text='Track color changes',
82                               variable=self.__trackp,
83                               relief=GROOVE,
84                               command=self.__toggletrack)
85        self.__t.pack(fill=X, expand=YES)
86        frame = self.__frame = Frame(root)
87        frame.pack()
88        #
89        # labels
90        self.__labels = []
91        row = 2
92        for text in ('Text:', 'Selection:', 'Insertion:'):
93            l = Label(frame, text=text)
94            l.grid(row=row, column=0, sticky=E)
95            self.__labels.append(l)
96            row += 1
97        col = 1
98        for text in ('Foreground', 'Background'):
99            l = Label(frame, text=text)
100            l.grid(row=1, column=col)
101            self.__labels.append(l)
102            col += 1
103        #
104        # radios
105        self.__radios = []
106        for col in (1, 2):
107            for row in (2, 3, 4):
108                # there is no insertforeground option
109                if row==4 and col==1:
110                    continue
111                r = Radiobutton(frame, variable=self.__which,
112                                value=(row-2)*2 + col-1,
113                                command=self.__set_color)
114                r.grid(row=row, column=col)
115                self.__radios.append(r)
116        self.__toggletrack()
117
118    def __quit(self, event=None):
119        self.__root.quit()
120
121    def withdraw(self, event=None):
122        self.__root.withdraw()
123
124    def deiconify(self, event=None):
125        self.__root.deiconify()
126
127    def __forceupdate(self, event=None):
128        self.__sb.update_views_current()
129
130    def __toggletrack(self, event=None):
131        if self.__trackp.get():
132            state = NORMAL
133            fg = self.__radios[0]['foreground']
134        else:
135            state = DISABLED
136            fg = self.__radios[0]['disabledforeground']
137        for r in self.__radios:
138            r.configure(state=state)
139        for l in self.__labels:
140            l.configure(foreground=fg)
141
142    def __set_color(self, event=None):
143        which = self.__which.get()
144        text = self.__text
145        if which == 0:
146            color = text['foreground']
147        elif which == 1:
148            color = text['background']
149        elif which == 2:
150            color = text['selectforeground']
151        elif which == 3:
152            color = text['selectbackground']
153        elif which == 5:
154            color = text['insertbackground']
155        try:
156            red, green, blue = ColorDB.rrggbb_to_triplet(color)
157        except ColorDB.BadColor:
158            # must have been a color name
159            red, green, blue = self.__sb.colordb().find_byname(color)
160        self.__sb.update_views(red, green, blue)
161
162    def update_yourself(self, red, green, blue):
163        if self.__trackp.get():
164            colorname = ColorDB.triplet_to_rrggbb((red, green, blue))
165            which = self.__which.get()
166            text = self.__text
167            if which == 0:
168                text.configure(foreground=colorname)
169            elif which == 1:
170                text.configure(background=colorname)
171            elif which == 2:
172                text.configure(selectforeground=colorname)
173            elif which == 3:
174                text.configure(selectbackground=colorname)
175            elif which == 5:
176                text.configure(insertbackground=colorname)
177
178    def save_options(self, optiondb):
179        optiondb['TRACKP'] = self.__trackp.get()
180        optiondb['WHICH'] = self.__which.get()
181        optiondb['TEXT'] = self.__text.get(0.0, 'end - 1c')
182        optiondb['TEXTSEL'] = self.__text.tag_ranges(SEL)[0:2]
183        optiondb['TEXTINS'] = self.__text.index(INSERT)
184        optiondb['TEXTFG'] = self.__text['foreground']
185        optiondb['TEXTBG'] = self.__text['background']
186        optiondb['TEXT_SFG'] = self.__text['selectforeground']
187        optiondb['TEXT_SBG'] = self.__text['selectbackground']
188        optiondb['TEXT_IBG'] = self.__text['insertbackground']
189