-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtextedit-1.tm
More file actions
285 lines (254 loc) · 9.73 KB
/
textedit-1.tm
File metadata and controls
285 lines (254 loc) · 9.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# Copyright © 2025 Mark Summerfield. All rights reserved.
package require html 1
package require ntext 1
package require scrollutil_tile 2
package require ui
oo::class create TextEdit {
variable Frame
variable Text
variable Completion
variable CompletionMenu
variable ContextMenu
}
package require textedit_actions
package require textedit_export
package require textedit_export_html
package require textedit_import
package require textedit_initialize
package require textedit_serialize
oo::define TextEdit classmethod make_color_menu {the_menu the_callback} {
# K E N B L C T V G I A W D O R P U M
const INDEXES {4 2 0 0 0 0 0 3 0 1 1 3 3 0 0 0 1 0}
foreach index $INDEXES {name color} [TextEdit colors] {
$the_menu add command -underline $index \
-image [my swatch $color $::MENU_ICON_SIZE] \
-compound left -label [string totitle $name] \
-command "$the_callback $name"
}
}
oo::define TextEdit classmethod swatch {color size} {
const R [expr {max(3, $size / 4.0)}]
const W [expr {$R + 2.5}]
image create photo -data "<svg width=\"$size\" height=\"$size\">
<rect x=\"0\" y=\"0\" width=\"$size\" height=\"$size\" rx=\"$R\"
ry=\"$R\" fill=\"$color\" stroke-width=\"$W\" stroke=\"white\">
</svg>"
}
oo::define TextEdit constructor {parent {family ""} {size 0}} {
classvariable N
if {![string match *. $parent]} { set parent $parent. }
set Frame ${parent}tf#[incr N] ;# unique
ttk::frame $Frame
set sa [scrollutil::scrollarea $Frame.sa -xscrollbarmode none]
set Text [text $Frame.sa.txt -undo 1 -wrap word]
$sa setwidget $Text
pack $sa -fill both -expand 1
set Completion 1
set CompletionMenu [menu $Frame.completionMenu]
my MakeContextMenu
my MakeBindings
my make_fonts $family $size
my make_tags
}
oo::define TextEdit method completion {} { return $Completion }
oo::define TextEdit method set_completion value { set Completion $value }
oo::define TextEdit method MakeContextMenu {} {
set ContextMenu [menu $Frame.contextMenu]
$ContextMenu add command -command [callback apply_style highlight] \
-label Highlight -underline 0 -compound left \
-image [ui::icon draw-highlight.svg $::MENU_ICON_SIZE]
$ContextMenu add separator
my make_color_menu $ContextMenu [callback apply_color]
}
oo::define TextEdit method MakeBindings {} {
bindtags $Text [list $Text Ntext [winfo toplevel $Text] all]
bind $Text <<ContextMenu>> "tk_popup $ContextMenu %X %Y"
bind $Text <BackSpace> [callback on_bs]
bind $Text <Control-Delete> [callback on_ctrl_del]
bind $Text <Control-BackSpace> [callback on_ctrl_bs]
bind $Text <Control-a> [callback on_ctrl_a]
bind $Text <Double-1> [callback on_double_click]
bind $Text <Control-Return> [callback on_ctrl_return]
bind $Text <Return> [callback on_return]
bind $Text <Tab> [callback on_tab]
bind $Text <'> [callback on_single_quote]
}
oo::define TextEdit method make_fonts {family size} {
if {$family eq ""} {
set family [font configure TkDefaultFont -family]
}
if {!$size} {
set size [expr {1 + [font configure TkDefaultFont -size]}]
}
foreach name {Sans Small Bold Italic BoldItalic} {
catch { font delete $name }
}
font create Sans -family $family -size $size
font create Small -family $family \
-size [expr {int(round($size * 0.75))}]
font create Bold -family $family -size $size -weight bold
font create Italic -family $family -size $size -slant italic
font create BoldItalic -family $family -size $size -weight bold \
-slant italic
set tab [expr {4 * [font measure Sans n]}]
$Text configure -font Sans -tabstyle wordprocessor -tabs "$tab left"
}
oo::define TextEdit method make_tags {} {
classvariable URL_UL_COLOR
classvariable HIGHLIGHT_COLOR
classvariable COLOR_FOR_TAG
$Text tag configure sub -font Small -offset -3p
$Text tag configure sup -font Small -offset 3p
$Text tag configure ul -underline 1
$Text tag configure strike -overstrike 1 -overstrikefg #FF1A1A
$Text tag configure center -justify center
$Text tag configure right -justify right
$Text tag configure url -underline 1 -underlinefg $URL_UL_COLOR
$Text tag configure bold -font Bold
$Text tag configure italic -font Italic
$Text tag configure bolditalic -font BoldItalic
$Text tag configure highlight -background $HIGHLIGHT_COLOR
set bwidth [font measure Sans "• "]
set twidth [font measure Sans "nnnn"]
# DEBUG: -background #E0FFFF
$Text tag configure bindent0 -lmargin2 $bwidth
# DEBUG: -background #ADFFFF
$Text tag configure bindent1 -lmargin1 $twidth \
-lmargin2 [expr {$twidth + $bwidth}]
dict for {key value} $COLOR_FOR_TAG {
$Text tag configure $key -foreground $value
}
}
oo::define TextEdit classmethod filetypes {} {
variable FILETYPES
return $FILETYPES
}
oo::define TextEdit classmethod colors {} {
variable COLOR_FOR_TAG
return $COLOR_FOR_TAG
}
oo::define TextEdit method unknown {the_method args} {
$Text $the_method {*}$args
}
oo::define TextEdit method focus {} { focus $Text }
oo::define TextEdit method ttk_frame {} { return $Frame }
oo::define TextEdit method tk_text {} { return $Text }
oo::define TextEdit method isempty {} {
expr {[string trim [$Text get 1.0 end]] eq ""}
}
oo::define TextEdit method clear {} {
$Text delete 1.0 end
$Text edit reset
$Text edit modified 0
}
oo::define TextEdit method after_load {{index insert}} {
my highlight_urls
$Text edit reset
$Text edit modified 0
if {$index ne "insert"} { $Text mark set insert $index }
$Text see $index
}
oo::define TextEdit method first_line {} { string trim [$Text get 1.0 2.0] }
oo::define TextEdit method highlight_urls {} {
foreach i [$Text search -all -regexp {(?:https?://|~/)} 1.0] {
set j [$Text search -regexp {[\s>]} $i]
if {[$Text get "$j -1 char"] eq "."} {
set j [$Text index "$j -1 char"]
}
$Text tag add url $i $j
}
}
oo::define TextEdit method selected {} {
if {[set indexes [$Text tag ranges sel]] ne ""} {
return $indexes
}
return "[$Text index "insert wordstart"] [$Text index "insert wordend"]"
}
oo::define TextEdit method get_whole_word {} {
set a [$Text index "insert linestart"]
set b [$Text index "insert lineend"]
set c [$Text index "insert wordstart"]
set i [$Text search -backwards -exact " " $c "$a -1 char"]
if {$i eq ""} { set i $a }
set j [$Text search -exact " " insert "$b +1 char"]
if {$j eq ""} { set j [$Text index $b] }
string trim [string trimright [$Text get $i $j] ",;:!?."]
}
oo::define TextEdit method apply_style style {
my apply_style_to [my selected] $style
}
oo::define TextEdit method apply_style_to {indexes style} {
if {$indexes ne ""} {
set tags [$Text tag names [lindex $indexes 0]]
if {$style eq "bold" && "bolditalic" in $tags} {
$Text tag remove bolditalic {*}$indexes
$Text tag add italic {*}$indexes
} elseif {$style eq "italic" && "bolditalic" in $tags} {
$Text tag remove bolditalic {*}$indexes
$Text tag add bold {*}$indexes
} elseif {($style eq "bold" && "italic" in $tags) ||
($style eq "italic" && "bold" in $tags)} {
$Text tag remove bold {*}$indexes
$Text tag remove italic {*}$indexes
$Text tag add bolditalic {*}$indexes
} elseif {$style eq "bold" && "bold" in $tags} {
$Text tag remove bold {*}$indexes
} elseif {$style eq "italic" && "italic" in $tags} {
$Text tag remove italic {*}$indexes
} elseif {$style eq "highlight" && "highlight" in $tags} {
$Text tag remove highlight {*}$indexes
} elseif {$style eq "sub" && "sub" in $tags} {
$Text tag remove sub {*}$indexes
} elseif {$style eq "sup" && "sup" in $tags} {
$Text tag remove sup {*}$indexes
} elseif {$style eq "ul" && "ul" in $tags} {
$Text tag remove ul {*}$indexes
} elseif {$style eq "strike" && "strike" in $tags} {
$Text tag remove strike {*}$indexes
} else {
$Text tag add $style {*}$indexes
}
$Text edit modified 1
}
}
oo::define TextEdit method apply_align align {
set i [$Text index "insert linestart"]
set j [$Text index "insert lineend"]
my apply_align_to [list $i $j] $align
}
oo::define TextEdit method apply_align_to {indexes align} {
if {$indexes ne ""} {
if {$align eq "left"} {
$Text tag remove center {*}$indexes
$Text tag remove right {*}$indexes
} else {
set tags [$Text tag names [lindex $indexes 0]]
if {$align eq "center" && "center" in $tags} {
$Text tag remove center {*}$indexes
} elseif {$align eq "right" && "right" in $tags} {
$Text tag remove right {*}$indexes
} else {
if {$align eq "center" && "right" in $tags} {
$Text tag remove right {*}$indexes
} elseif {$align eq "right" && "center" in $tags} {
$Text tag remove center {*}$indexes
}
$Text tag add $align {*}$indexes
}
}
$Text edit modified 1
}
}
oo::define TextEdit method apply_color color {
my apply_color_to [my selected] $color
}
oo::define TextEdit method apply_color_to {indexes color} {
classvariable COLOR_FOR_TAG
foreach tag [dict keys $COLOR_FOR_TAG] {
$Text tag remove $tag {*}$indexes
}
if {$color ne "black"} {
$Text tag add $color {*}$indexes
}
$Text edit modified 1
}