1998-10-02 13:20:14 -03:00
|
|
|
"""TextViewer class.
|
|
|
|
|
|
|
|
The TextViewer allows you to see how the selected color would affect various
|
|
|
|
characteristics of a Tk text widget. This is an output viewer only.
|
|
|
|
|
|
|
|
In the top part of the window is a standard text widget with some sample text
|
|
|
|
in it. You are free to edit this text in any way you want (TBD: allow you to
|
|
|
|
change font characteristics). If you want changes in other viewers to update
|
|
|
|
text characteristics, turn on Track color changes.
|
|
|
|
|
|
|
|
To select which characteristic tracks the change, select one of the radio
|
|
|
|
buttons in the window below. Text foreground and background affect the text
|
|
|
|
in the window above. The Selection is what you see when you click the middle
|
|
|
|
button and drag it through some text. The Insertion is the insertion cursor
|
|
|
|
in the text window (which only has a background).
|
|
|
|
"""
|
|
|
|
|
1998-10-01 13:45:32 -03:00
|
|
|
from Tkinter import *
|
|
|
|
import ColorDB
|
|
|
|
|
|
|
|
class TextViewer:
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 00:25:59 -03:00
|
|
|
def __init__(self, switchboard, master=None):
|
1998-10-01 13:45:32 -03:00
|
|
|
self.__sb = switchboard
|
1998-10-20 17:45:46 -03:00
|
|
|
optiondb = switchboard.optiondb()
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 00:25:59 -03:00
|
|
|
root = self.__root = Toplevel(master, class_='Pynche')
|
|
|
|
root.protocol('WM_DELETE_WINDOW', self.withdraw)
|
1998-10-05 18:31:37 -03:00
|
|
|
root.title('Pynche Text Window')
|
1998-10-01 13:45:32 -03:00
|
|
|
root.iconname('Pynche Text Window')
|
|
|
|
root.bind('<Alt-q>', self.__quit)
|
|
|
|
root.bind('<Alt-Q>', self.__quit)
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 00:25:59 -03:00
|
|
|
root.bind('<Alt-w>', self.withdraw)
|
|
|
|
root.bind('<Alt-W>', self.withdraw)
|
1998-10-01 13:45:32 -03:00
|
|
|
#
|
|
|
|
# create the text widget
|
|
|
|
#
|
|
|
|
self.__text = Text(root, relief=SUNKEN,
|
1998-10-20 17:45:46 -03:00
|
|
|
background=optiondb.get('TEXTBG', 'black'),
|
|
|
|
foreground=optiondb.get('TEXTFG', 'white'),
|
1998-10-01 13:45:32 -03:00
|
|
|
width=35, height=15)
|
1998-10-20 17:45:46 -03:00
|
|
|
sfg = optiondb.get('TEXT_SFG')
|
|
|
|
if sfg:
|
|
|
|
self.__text.configure(selectforeground=sfg)
|
|
|
|
sbg = optiondb.get('TEXT_SBG')
|
|
|
|
if sbg:
|
|
|
|
self.__text.configure(selectbackground=sbg)
|
|
|
|
ibg = optiondb.get('TEXT_IBG')
|
|
|
|
if ibg:
|
|
|
|
self.__text.configure(insertbackground=ibg)
|
1998-10-01 13:45:32 -03:00
|
|
|
self.__text.pack()
|
1998-10-20 17:45:46 -03:00
|
|
|
self.__text.insert(0.0, optiondb.get('TEXT', '''\
|
1998-10-01 13:45:32 -03:00
|
|
|
Insert some stuff here and play
|
|
|
|
with the buttons below to see
|
|
|
|
how the colors interact in
|
1998-10-06 18:40:22 -03:00
|
|
|
textual displays.
|
|
|
|
|
|
|
|
See how the selection can also
|
|
|
|
be affected by tickling the buttons
|
1998-10-20 17:45:46 -03:00
|
|
|
and choosing a color.'''))
|
|
|
|
insert = optiondb.get('TEXTINS')
|
|
|
|
if insert:
|
|
|
|
self.__text.mark_set(INSERT, insert)
|
|
|
|
try:
|
|
|
|
start, end = optiondb.get('TEXTSEL', (6.0, END))
|
|
|
|
self.__text.tag_add(SEL, start, end)
|
|
|
|
except ValueError:
|
|
|
|
# selection wasn't set
|
|
|
|
pass
|
|
|
|
self.__text.focus_set()
|
1998-10-01 13:45:32 -03:00
|
|
|
#
|
|
|
|
# variables
|
|
|
|
self.__trackp = BooleanVar()
|
1998-10-20 17:45:46 -03:00
|
|
|
self.__trackp.set(optiondb.get('TRACKP', 0))
|
1998-10-01 13:45:32 -03:00
|
|
|
self.__which = IntVar()
|
1998-10-20 17:45:46 -03:00
|
|
|
self.__which.set(optiondb.get('WHICH', 0))
|
1998-10-01 13:45:32 -03:00
|
|
|
#
|
|
|
|
# track toggle
|
|
|
|
self.__t = Checkbutton(root, text='Track color changes',
|
|
|
|
variable=self.__trackp,
|
1998-10-06 15:46:57 -03:00
|
|
|
relief=GROOVE,
|
|
|
|
command=self.__toggletrack)
|
1998-10-01 13:45:32 -03:00
|
|
|
self.__t.pack(fill=X, expand=YES)
|
|
|
|
frame = self.__frame = Frame(root)
|
|
|
|
frame.pack()
|
|
|
|
#
|
|
|
|
# labels
|
|
|
|
self.__labels = []
|
|
|
|
row = 2
|
|
|
|
for text in ('Text:', 'Selection:', 'Insertion:'):
|
|
|
|
l = Label(frame, text=text)
|
|
|
|
l.grid(row=row, column=0, sticky=E)
|
|
|
|
self.__labels.append(l)
|
|
|
|
row = row + 1
|
|
|
|
col = 1
|
|
|
|
for text in ('Foreground', 'Background'):
|
|
|
|
l = Label(frame, text=text)
|
|
|
|
l.grid(row=1, column=col)
|
|
|
|
self.__labels.append(l)
|
|
|
|
col = col + 1
|
|
|
|
#
|
|
|
|
# radios
|
|
|
|
self.__radios = []
|
|
|
|
val = 0
|
|
|
|
for col in (1, 2):
|
|
|
|
for row in (2, 3, 4):
|
|
|
|
# there is no insertforeground option
|
|
|
|
if row==4 and col==1:
|
|
|
|
continue
|
|
|
|
r = Radiobutton(frame, variable=self.__which,
|
1999-04-27 12:56:53 -03:00
|
|
|
value=(row-2)*2 + col-1,
|
|
|
|
command=self.__set_color)
|
1998-10-01 13:45:32 -03:00
|
|
|
r.grid(row=row, column=col)
|
|
|
|
self.__radios.append(r)
|
1998-10-06 15:46:57 -03:00
|
|
|
self.__toggletrack()
|
1998-10-01 13:45:32 -03:00
|
|
|
|
|
|
|
def __quit(self, event=None):
|
1998-10-06 16:48:35 -03:00
|
|
|
self.__root.quit()
|
1998-10-01 13:45:32 -03:00
|
|
|
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 00:25:59 -03:00
|
|
|
def withdraw(self, event=None):
|
1998-10-01 13:45:32 -03:00
|
|
|
self.__root.withdraw()
|
|
|
|
|
|
|
|
def deiconify(self, event=None):
|
|
|
|
self.__root.deiconify()
|
|
|
|
|
|
|
|
def __forceupdate(self, event=None):
|
|
|
|
self.__sb.update_views_current()
|
|
|
|
|
1998-10-06 15:46:57 -03:00
|
|
|
def __toggletrack(self, event=None):
|
|
|
|
if self.__trackp.get():
|
|
|
|
state = NORMAL
|
|
|
|
fg = self.__radios[0]['foreground']
|
|
|
|
else:
|
|
|
|
state = DISABLED
|
|
|
|
fg = self.__radios[0]['disabledforeground']
|
|
|
|
for r in self.__radios:
|
|
|
|
r.configure(state=state)
|
|
|
|
for l in self.__labels:
|
|
|
|
l.configure(foreground=fg)
|
|
|
|
|
1999-04-27 12:56:53 -03:00
|
|
|
def __set_color(self, event=None):
|
|
|
|
which = self.__which.get()
|
|
|
|
text = self.__text
|
|
|
|
if which == 0:
|
|
|
|
color = text['foreground']
|
|
|
|
elif which == 1:
|
|
|
|
color = text['background']
|
|
|
|
elif which == 2:
|
|
|
|
color = text['selectforeground']
|
|
|
|
elif which == 3:
|
|
|
|
color = text['selectbackground']
|
|
|
|
elif which == 5:
|
|
|
|
color = text['insertbackground']
|
|
|
|
try:
|
|
|
|
red, green, blue = ColorDB.rrggbb_to_triplet(color)
|
|
|
|
except ColorDB.BadColor:
|
|
|
|
# must have been a color name
|
|
|
|
red, green, blue = self.__sb.colordb().find_byname(color)
|
|
|
|
self.__sb.update_views(red, green, blue)
|
|
|
|
|
1998-10-01 13:45:32 -03:00
|
|
|
def update_yourself(self, red, green, blue):
|
1998-10-06 15:46:57 -03:00
|
|
|
if self.__trackp.get():
|
|
|
|
colorname = ColorDB.triplet_to_rrggbb((red, green, blue))
|
|
|
|
which = self.__which.get()
|
1999-04-27 12:56:53 -03:00
|
|
|
text = self.__text
|
1998-10-06 15:46:57 -03:00
|
|
|
if which == 0:
|
1999-04-27 12:56:53 -03:00
|
|
|
text.configure(foreground=colorname)
|
1998-10-06 15:46:57 -03:00
|
|
|
elif which == 1:
|
1999-04-27 12:56:53 -03:00
|
|
|
text.configure(background=colorname)
|
1998-10-06 15:46:57 -03:00
|
|
|
elif which == 2:
|
1999-04-27 12:56:53 -03:00
|
|
|
text.configure(selectforeground=colorname)
|
1998-10-06 15:46:57 -03:00
|
|
|
elif which == 3:
|
1999-04-27 12:56:53 -03:00
|
|
|
text.configure(selectbackground=colorname)
|
1998-10-06 15:46:57 -03:00
|
|
|
elif which == 5:
|
1999-04-27 12:56:53 -03:00
|
|
|
text.configure(insertbackground=colorname)
|
1998-10-20 17:45:46 -03:00
|
|
|
|
|
|
|
def save_options(self, optiondb):
|
|
|
|
optiondb['TRACKP'] = self.__trackp.get()
|
|
|
|
optiondb['WHICH'] = self.__which.get()
|
|
|
|
optiondb['TEXT'] = self.__text.get(0.0, 'end - 1c')
|
|
|
|
optiondb['TEXTSEL'] = self.__text.tag_ranges(SEL)[0:2]
|
|
|
|
optiondb['TEXTINS'] = self.__text.index(INSERT)
|
|
|
|
optiondb['TEXTFG'] = self.__text['foreground']
|
|
|
|
optiondb['TEXTBG'] = self.__text['background']
|
|
|
|
optiondb['TEXT_SFG'] = self.__text['selectforeground']
|
|
|
|
optiondb['TEXT_SBG'] = self.__text['selectbackground']
|
|
|
|
optiondb['TEXT_IBG'] = self.__text['insertbackground']
|