Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | # Gedi master advanced text editor. |
2 | ||
3 | use Tk::TextEdit; | |
4 | ||
5 | use vars qw/$TOP/; | |
6 | ||
7 | my $TOP; | |
8 | my $text_frame; | |
9 | my $counter_frame; | |
10 | my $textwindow; | |
11 | my $current_line_label; | |
12 | my $total_line_label; | |
13 | my $current_column_label; | |
14 | my $insert_overstrike_mode_label; | |
15 | my $about_pop_up_reference; | |
16 | my $menu; | |
17 | my $help_menu; | |
18 | ||
19 | sub about_pop_up | |
20 | { | |
21 | my $name = ref($about_pop_up_reference); | |
22 | if (defined($about_pop_up_reference)) | |
23 | { | |
24 | $about_pop_up_reference->raise; | |
25 | $about_pop_up_reference->focus; | |
26 | } | |
27 | else | |
28 | { | |
29 | my $pop = $TOP->Toplevel(); | |
30 | $pop->title("About"); | |
31 | ||
32 | $pop->Label(text=>"Gedi (Gregs EDItor)")->pack(); | |
33 | $pop->Label(text=>"Ver. 1.0")->pack(); | |
34 | $pop->Label(text=>"Copyright 1999")->pack(); | |
35 | $pop->Label(text=>"Greg London")->pack(); | |
36 | $pop->Label(text=>"All Rights Reserved.")->pack(); | |
37 | $pop->Label(text=>"This program is free software.")->pack(); | |
38 | $pop->Label(text=>"You can redistribute it and/or")->pack(); | |
39 | $pop->Label(text=>"modify it under the same terms")->pack(); | |
40 | $pop->Label(text=>"as Perl itself.")->pack(); | |
41 | $pop->Label(text=>"Special Thanks to")->pack(); | |
42 | $pop->Label(text=>"Nick Ing-Simmons.")->pack(); | |
43 | ||
44 | my $button_ok = $pop->Button(text=>'OK', | |
45 | command => sub {$pop->destroy(); | |
46 | $about_pop_up_reference = undef; | |
47 | } ) | |
48 | ->pack(); | |
49 | $pop->resizable('no','no'); | |
50 | $about_pop_up_reference = $pop; | |
51 | } | |
52 | } | |
53 | ||
54 | ||
55 | sub update_indicators | |
56 | { | |
57 | my ($line,$column)= split(/\./,$textwindow->index('insert')); | |
58 | $current_line_label->configure (text=> "line: $line"); | |
59 | $current_column_label->configure (text=> "column: $column"); | |
60 | ||
61 | my ($last_line,$last_col) = split(/\./,$textwindow->index('end')); | |
62 | $total_line_label->configure (text=> "total lines: $last_line"); | |
63 | ||
64 | my $mode = $textwindow->OverstrikeMode; | |
65 | my $overstrke_insert='Insert Mode'; | |
66 | if ($mode) | |
67 | {$overstrke_insert='Overstrike Mode';} | |
68 | $insert_overstrike_mode_label->configure | |
69 | (text=> "$overstrke_insert"); | |
70 | ||
71 | my $filename = $textwindow->FileName; | |
72 | $filename = 'NoName' unless(defined($filename)); | |
73 | my $edit_flag=''; | |
74 | if($textwindow->numberChanges) | |
75 | {$edit_flag='edited';} | |
76 | $TOP->configure(-title => "Gedi $edit_flag $filename"); | |
77 | $textwindow->idletasks; | |
78 | ||
79 | } | |
80 | ||
81 | ||
82 | ||
83 | ||
84 | ||
85 | ||
86 | sub Gedi { | |
87 | my($demo) = @_; | |
88 | $TOP = $MW->WidgetDemo( | |
89 | -name => $demo, | |
90 | -text => 'Gedi master advanced text editor ', | |
91 | -geometry_manager => 'grid', | |
92 | -title => 'GEDI Text Editor', | |
93 | -iconname => 'GEDI', | |
94 | ); | |
95 | ||
96 | ||
97 | ||
98 | $text_frame = $TOP->Frame->pack | |
99 | (-anchor=>'nw', expand=>'yes', -fill => 'both'); # autosizing | |
100 | $counter_frame = $TOP->Frame->pack(-anchor=>'nw'); | |
101 | ||
102 | $textwindow = $text_frame->Scrolled( | |
103 | 'TextEdit', | |
104 | exportselection => 'true', # 'sel' tag is associated with selections | |
105 | # initial height, if it isnt 1, then autosizing fails | |
106 | # once window shrinks below height | |
107 | # and the line counters go off the screen. | |
108 | # seems to be a problem with the Tk::pack command; | |
109 | height => 40, | |
110 | -background => 'white', | |
111 | -wrap=> 'none', | |
112 | -setgrid => 'true', # use this for autosizing | |
113 | -scrollbars =>'se') | |
114 | -> pack(-expand => 'yes' , -fill => 'both'); # autosizing | |
115 | ||
116 | $TOP->protocol('WM_DELETE_WINDOW'=> | |
117 | sub{$textwindow->ConfirmExit;} | |
118 | ); | |
119 | ||
120 | $SIG{INT} = sub {$textwindow->ConfirmExit;}; | |
121 | ||
122 | $current_line_label = $counter_frame | |
123 | -> Label(text=>'line: 1') | |
124 | -> grid(-row=>1,-column=>1, -sticky=>'nw' ); | |
125 | ||
126 | $total_line_label = $counter_frame | |
127 | -> Label(text=>'total lines: 1') | |
128 | -> grid(-row=>2,-column=>1, -sticky=>'nw' ); | |
129 | ||
130 | $current_column_label = $counter_frame | |
131 | -> Label(text=>'column: 0') | |
132 | -> grid(-row=>3,-column=>1, -sticky=>'nw' ); | |
133 | ||
134 | $insert_overstrike_mode_label = $counter_frame | |
135 | -> Label(text=>' ') | |
136 | -> grid(-row=>5,-column=>1, -sticky=>'nw' ); | |
137 | ||
138 | $textwindow->SetGUICallbacks ( | |
139 | [ | |
140 | \&update_indicators, | |
141 | sub{$textwindow->HighlightAllPairsBracketingCursor} | |
142 | ] | |
143 | ); | |
144 | ||
145 | $menu = $textwindow->menu; | |
146 | ||
147 | $TOP->configure(-menu => $menu); | |
148 | ||
149 | $help_menu = $menu->cascade(-label=>'~Help', -tearoff => 0, -menuitems => [ | |
150 | [Command => 'A~bout', -command => \&about_pop_up] | |
151 | ]); | |
152 | ||
153 | ||
154 | #$TOP->minsize(30,1); | |
155 | #$TOP->geometry("80x24"); | |
156 | ||
157 | while(<DATA>) | |
158 | {$textwindow->insert('insert',$_);} | |
159 | $textwindow->ResetUndo; | |
160 | ||
161 | $textwindow->CallNextGUICallback; | |
162 | ||
163 | } | |
164 | ||
165 | ||
166 | __DATA__ | |
167 | ||
168 | Tk800.015 contains many modifications to the | |
169 | text based modules, as well as new text modules | |
170 | and an application that uses them all. | |
171 | Text.pm, TextUndo.pm, TextEdit.pm, and gedi | |
172 | have all been updated since the release prior | |
173 | to Tk800.015. | |
174 | ||
175 | This demo contains a rundown of all the features | |
176 | of the text modules, and | |
177 | ||
178 | What is available in the text modules? | |
179 | ================================================ | |
180 | ||
181 | Text.pm | |
182 | ======== | |
183 | ||
184 | Text.pm is the base text editing module. | |
185 | Beyond the core functionality of typing text, | |
186 | Text.pm has built in menu support for basic | |
187 | editing features such as Find/Replace text, | |
188 | Copy/Cut/Paste, Goto Line Number, and What | |
189 | Line Number queries. | |
190 | ||
191 | These functions are available simply by right | |
192 | clicking the mouse over the text area. Doing | |
193 | so will cause a pop-up menu to appear which will | |
194 | contain cascading menus to give access to all of | |
195 | these new functions. | |
196 | ||
197 | Many of these functions will create their own | |
198 | pop-up windows. Find/Replace will create a pop-up | |
199 | window which contains an entry for text to | |
200 | find, an entry for replace text, a number of | |
201 | radio buttons to control options such as | |
202 | case sensitivity, and several command buttons to | |
203 | perform functions such as Find, Find All, | |
204 | Replace, Replace All. | |
205 | ||
206 | All of these features have corresponding methods | |
207 | built into the Text widget. This allows the basic | |
208 | functions to be built into the widget, and also | |
209 | allows added features to be built on the lower | |
210 | level methods as needed. No one should have to | |
211 | reinvent the wheel when it comes to text editing | |
212 | features. | |
213 | ||
214 | Insert and Overstrike modes are also supported | |
215 | in the Text.pm module. Pressing the <Insert> | |
216 | key will toggle modes back and forth. | |
217 | ||
218 | Column based copy/cut/paste features are also | |
219 | available in the Text.pm module. They are bound | |
220 | to the following keys: | |
221 | ||
222 | <F1> clipboardColumnCopy | |
223 | <F2> clipboardColumnCut | |
224 | <F3> clipboardColumnPaste | |
225 | ||
226 | Currently, column based operations are beta versions. | |
227 | They compensate for tabs, but they will not behave | |
228 | properly unless the text is all the same font, and | |
229 | is the same width per character. | |
230 | ||
231 | Hopefully some future version of Text.pm will correct | |
232 | for this deficiency. | |
233 | ||
234 | Column paste should work with overstrike mode. | |
235 | ||
236 | ||
237 | TextUndo.pm | |
238 | ============= | |
239 | ||
240 | TextUndo.pm is the second level module, being | |
241 | derived from the Text.pm module. As it's name | |
242 | implies, TextUndo supports "UNDO" capability. | |
243 | It now also supports "REDO" capability. | |
244 | ||
245 | Undo/redo works on user typed commands and | |
246 | also programmatically, so that any application | |
247 | that causes text to be inserted or deleted | |
248 | can be undone/redone, whether it was directly | |
249 | typed by the user or indirectly through another | |
250 | method. | |
251 | ||
252 | The undo/redo functions support tags, so that | |
253 | if you delete text with tags, undo will re-insert | |
254 | the text and re-tag it as well. This will eventually | |
255 | allow the text modules to support more sophisticated | |
256 | word processing type features. Such functionality | |
257 | should be available in a future release of the | |
258 | text modules. | |
259 | ||
260 | The TextUndo.pm module also has several added | |
261 | features to support file based operations. | |
262 | File based methods include ->Save, ->Load, and | |
263 | ->Include. All methods take a filename as a | |
264 | parameter. These methods will create a progress | |
265 | widget to indicate the progress of the operation. | |
266 | ||
267 | The other feature of the TextUndo.pm module | |
268 | is the ConfirmDiscard method. This method checks to | |
269 | see if the text has been modified since it was | |
270 | last saved. If it has been modified, and the | |
271 | it will create a pop-up menu asking the user | |
272 | if they want to save the text to a file before | |
273 | exiting. This method can easily be tied into | |
274 | the exit routines, and signal handlers, to provide | |
275 | a consistent "save before exit?" feel. | |
276 | ||
277 | TextEdit.pm | |
278 | ============= | |
279 | ||
280 | The TextEdit.pm is a new module in prototype version | |
281 | which adds further features to the text modules. | |
282 | TextEdit is based off of the TextUndo module, | |
283 | and so has all of the features of TextUndo and | |
284 | Text. | |
285 | ||
286 | Features of the TextEdit.pm module include | |
287 | parenthesis matching. The module looks at the | |
288 | current cursor position and then tries to find | |
289 | the parenthesis that bracket the cursor. | |
290 | Character pairs that are searched for are: | |
291 | () {} [] "" '' | |
292 | ||
293 | It also checks the position of the pairs to | |
294 | try to highlight bad positions. The module | |
295 | assumes that if the pairs are not on the same | |
296 | line or not on the same column, then there | |
297 | might be a missing parenthesis somewhere. | |
298 | Characters that appear to not align are | |
299 | highlighted in red. | |
300 | ||
301 | (quotations must start and end on the same line) | |
302 | ||
303 | ||
304 | PARENTHISIS MATCHING DEMO: | |
305 | move the cursor to the x between the quotes | |
306 | on the line below: | |
307 | ||
308 | ||
309 | { | |
310 | ( ) | |
311 | ( { } | |
312 | [ | |
313 | ' ">> x <<" ' | |
314 | [] ] | |
315 | ) | |
316 | ||
317 | } | |
318 | ||
319 | PARENTHESIS MISMATCHING DEMO: | |
320 | move the cursor to the x between the quotes | |
321 | on the line below: | |
322 | ||
323 | ||
324 | { | |
325 | ( ) | |
326 | ( <<RED possible error { } | |
327 | [ | |
328 | ' ">> x <<" ' | |
329 | [] ] | |
330 | ) <<RED possible error | |
331 | ||
332 | } | |
333 | ||
334 | ||
335 | ||
336 | Another feature of the TextEdit module is support | |
337 | for application level indicators which reflect | |
338 | the status of certain internals. The line and | |
339 | column position of the cursor, the total length | |
340 | of the file, whether the widget is in insert or | |
341 | overstrike mode. Anytime anything occurs that could | |
342 | affect these values, a user supplied callback | |
343 | is invoked. This callback is supplied by the | |
344 | application so that the application can update | |
345 | whatever indicators it uses, however it implements | |
346 | them. | |
347 | ||
348 | One other feature of the TextEdit.pm module is | |
349 | block level text indention and block level text | |
350 | commenting. If a block of text is selected, | |
351 | that text can be indented or unindented wiht | |
352 | a single keystroke. It can also be commented | |
353 | out or uncommented as well. The keystroke bindings | |
354 | that support this are: | |
355 | ||
356 | <F5> IndentSelectedLines | |
357 | <F6> UnindentSelectedLines | |
358 | ||
359 | <F7> CommentSelectedLines | |
360 | <F8> UncommentSelectedLines | |
361 | ||
362 | These bindings only operate on the currently | |
363 | selected text. The indent string and the comment | |
364 | string can be programmed to be anything, but | |
365 | defaults to "\t" (tab) for indent and "#" for | |
366 | comments. | |
367 | ||
368 | (currently the widget hash is used to store these values. | |
369 | $w->{'INDENT_STRING'} and $w->{'LINE_COMMENT_STRING'} | |
370 | At some point in the future, this will be changed to | |
371 | use configure options to set these values. | |
372 | any application that changes these values should do | |
373 | so in such a way that when the TextEdit module changes, | |
374 | the application can be easily changed to handle this) | |
375 | ||
376 | ||
377 | ||
378 | gedi application | |
379 | ===================== | |
380 | gedi is short for Greg's EDItor. | |
381 | The "g" is soft, pronounced like a "j". | |
382 | ||
383 | The gedi application uses all of the features of | |
384 | the text modules, Text, TextUndo, and TextEdit. | |
385 | It supplies TextEdit with a callback to update | |
386 | the indicator displays. This information includes | |
387 | the current cursor position, insert/overstrike | |
388 | mode, length of the file, filename, and whether | |
389 | the file has been edited or not. | |
390 | ||
391 | The bottom of this display contains | |
392 | line number | |
393 | column number | |
394 | total lines | |
395 | insert/overstrike mode. | |
396 | ||
397 | The title bar contains | |
398 | filename | |
399 | and if the file has been edited, the word "edited". | |
400 | ||
401 | Where gedi is installed depends on your system, | |
402 | but it is part of the tarkit for Tk800.015 and above. | |
403 | ||
404 | gedi was created to be put a perl editor in with the | |
405 | perl tar kit. | |
406 | ||
407 | NOTE: THIS IS NOT THE ACTUAL GEDI APPLICATION, BUT | |
408 | A DEMO SET UP TO BE SIMILAR IN NATURE TO THE GEDI | |
409 | APPLICATION. THE ACTUAL GEDI APPLICATION IS PART OF | |
410 | THE TK800.015 TARKIT. WHERE IT IS LOCATED ON YOUR | |
411 | SYSTEM WILL VARY DEPENDING ON YOUR SYSTEM. ONCE | |
412 | YOU LOCATE THE GEDI APPLICATION, PUT IT IN YOUR | |
413 | EXECUTABLE PATH, AND YOU WILL BE ABLE TO USE IT AS | |
414 | A TEXT EDITOR. | |
415 | ||
416 | ||
417 | ||
418 | ||
419 | ||
420 |