1 /** 2 * Widget module. 3 * 4 * License: 5 * MIT. See LICENSE for full details. 6 */ 7 module tkd.widget.text; 8 9 /** 10 * Imports. 11 */ 12 import std.conv; 13 import tkd.element.uielement; 14 import tkd.image.image; 15 import tkd.widget.common.border; 16 import tkd.widget.common.color; 17 import tkd.widget.common.font; 18 import tkd.widget.common.height; 19 import tkd.widget.common.relief; 20 import tkd.widget.common.width; 21 import tkd.widget.common.xscrollcommand; 22 import tkd.widget.common.xview; 23 import tkd.widget.common.yscrollcommand; 24 import tkd.widget.common.yview; 25 import tkd.widget.textwrapmode; 26 import tkd.widget.widget; 27 28 /** 29 * A text widget displays one or more lines of text and allows that text to be 30 * edited. Text widgets support embedded widgets or embedded images. 31 * 32 * Example: 33 * --- 34 * auto text = new Text() 35 * .appendText("Text") 36 * .pack(); 37 * --- 38 * 39 * Common_Commands: 40 * These are injected common commands that can also be used with this widget. 41 * $(P 42 * $(LINK2 ./common/border.html, Border) $(BR) 43 * $(LINK2 ./common/color.html, Color) $(BR) 44 * $(LINK2 ./common/font.html, Font) $(BR) 45 * $(LINK2 ./common/height.html, Height) $(BR) 46 * $(LINK2 ./common/relief.html, Relief) $(BR) 47 * $(LINK2 ./common/width.html, Width) $(BR) 48 * $(LINK2 ./common/xscrollcommand.html, XScrollCommand) $(BR) 49 * $(LINK2 ./common/xview.html, XView) $(BR) 50 * $(LINK2 ./common/yscrollcommand.html, YScrollCommand) $(BR) 51 * $(LINK2 ./common/yview.html, YView) $(BR) 52 * ) 53 * 54 * Additional_Events: 55 * Additional events that can also be bound to using the $(LINK2 ../element/uielement.html#UiElement.bind, bind) method. 56 * $(P 57 * <<Clear>>, 58 * <<Copy>>, 59 * <<Cut>>, 60 * <<Modified>>, 61 * <<Paste>>, 62 * <<PasteSelection>>, 63 * <<PrevWindow>>, 64 * <<Redo>>, 65 * <<Selection>>, 66 * <<Undo>>, 67 * <Alt-Key>, 68 * <B1-Enter>, 69 * <B1-Leave>, 70 * <B1-Motion>, 71 * <B2-Motion>, 72 * <Button-1>, 73 * <Button-2>, 74 * <Button-4>, 75 * <Button-5>, 76 * <ButtonRelease-1>, 77 * <Control-Button-1>, 78 * <Control-Key-Down>, 79 * <Control-Key-End>, 80 * <Control-Key-Home>, 81 * <Control-Key-Left>, 82 * <Control-Key-Next>, 83 * <Control-Key-Prior>, 84 * <Control-Key-Right>, 85 * <Control-Key-Tab>, 86 * <Control-Key-Up>, 87 * <Control-Key-a>, 88 * <Control-Key-b>, 89 * <Control-Key-backslash>, 90 * <Control-Key-d>, 91 * <Control-Key-e>, 92 * <Control-Key-f>, 93 * <Control-Key-h>, 94 * <Control-Key-i>, 95 * <Control-Key-k>, 96 * <Control-Key-n>, 97 * <Control-Key-o>, 98 * <Control-Key-p>, 99 * <Control-Key-slash>, 100 * <Control-Key-space>, 101 * <Control-Key-t>, 102 * <Control-Key>, 103 * <Control-Shift-Key-Down>, 104 * <Control-Shift-Key-End>, 105 * <Control-Shift-Key-Home>, 106 * <Control-Shift-Key-Left>, 107 * <Control-Shift-Key-Right>, 108 * <Control-Shift-Key-Tab>, 109 * <Control-Shift-Key-Up>, 110 * <Control-Shift-Key-space>, 111 * <Double-Button-1>, 112 * <Double-Shift-Button-1>, 113 * <Key-BackSpace>, 114 * <Key-Delete>, 115 * <Key-Down>, 116 * <Key-End>, 117 * <Key-Escape>, 118 * <Key-F10>, 119 * <Key-Home>, 120 * <Key-Insert>, 121 * <Key-KP_Enter>, 122 * <Key-Left>, 123 * <Key-Next>, 124 * <Key-Prior>, 125 * <Key-Return>, 126 * <Key-Right>, 127 * <Key-Select>, 128 * <Key-Tab>, 129 * <Key-Up>, 130 * <Key>, 131 * <Meta-Key-BackSpace>, 132 * <Meta-Key-Delete>, 133 * <Meta-Key-b>, 134 * <Meta-Key-d>, 135 * <Meta-Key-f>, 136 * <Meta-Key-greater>, 137 * <Meta-Key-less>, 138 * <Meta-Key>, 139 * <MouseWheel>, 140 * <Shift-Button-1>, 141 * <Shift-Key-Down>, 142 * <Shift-Key-End>, 143 * <Shift-Key-Home>, 144 * <Shift-Key-Left>, 145 * <Shift-Key-Next>, 146 * <Shift-Key-Prior>, 147 * <Shift-Key-Right>, 148 * <Shift-Key-Select>, 149 * <Shift-Key-Tab>, 150 * <Shift-Key-Up>, 151 * <Triple-Button-1>, 152 * <Triple-Shift-Button-1>, 153 * ) 154 * 155 * See_Also: 156 * $(LINK2 ./widget.html, tkd.widget.widget) 157 */ 158 class Text : Widget, IXScrollable!(Text), IYScrollable!(Text) 159 { 160 /** 161 * Construct the widget. 162 * 163 * Params: 164 * parent = The parent of this widget. 165 * 166 * See_Also: 167 * $(LINK2 ../element/uielement.html, tkd.element.UiElement) $(BR) 168 */ 169 public this(UiElement parent = null) 170 { 171 super(parent); 172 this._elementId = "text"; 173 174 this._tk.eval("text %s -highlightthickness 0", this.id); 175 176 this.setUndoSupport(true); 177 this.setUndoLevels(25); 178 this.setWrapMode(TextWrapMode.word); 179 } 180 181 /** 182 * Set the amount of padding in the text widget. 183 * 184 * Params: 185 * padding = The amount of padding in the text widget. 186 * 187 * Returns: 188 * This widget to aid method chaining. 189 */ 190 public auto setPadding(this T)(int padding) 191 { 192 this._tk.eval("%s configure -padx %s -pady %s", this.id, padding, padding); 193 194 return cast(T) this; 195 } 196 197 /** 198 * Set if the widget is readonly or not. 199 * 200 * Params: 201 * readOnly = Flag to toggle readonly state. 202 * 203 * Returns: 204 * This widget to aid method chaining. 205 */ 206 public auto setReadOnly(this T)(bool readOnly = true) 207 { 208 if(readOnly) 209 { 210 this._tk.eval("%s configure -state disabled", this.id); 211 } 212 else 213 { 214 this._tk.eval("%s configure -state normal", this.id); 215 } 216 217 return cast(T) this; 218 } 219 220 /** 221 * Enable or disable undo support. 222 * 223 * Params: 224 * enable = True to enable undo support, false to disable it. 225 * 226 * Returns: 227 * This widget to aid method chaining. 228 */ 229 public auto setUndoSupport(this T)(bool enable) 230 { 231 this._tk.eval("%s configure -undo %s", this.id, enable); 232 233 return cast(T) this; 234 } 235 236 /** 237 * Set the number of undo levels the widget will support. 238 * 239 * Params: 240 * undoLevels = The number of undo levels the widget will support. 241 * 242 * Returns: 243 * This widget to aid method chaining. 244 */ 245 public auto setUndoLevels(this T)(int undoLevels) 246 { 247 this._tk.eval("%s configure -maxundo %s", this.id, undoLevels); 248 249 return cast(T) this; 250 } 251 252 /** 253 * Set the wrap mode of the text. 254 * 255 * Params: 256 * mode = The mode to wrap the text with. 257 * 258 * Returns: 259 * This widget to aid method chaining. 260 * 261 * See_Also: 262 * $(LINK2 ./textwrapmode.html, tkd.widget.textwrapmode) 263 */ 264 public auto setWrapMode(this T)(string mode) 265 { 266 this._tk.eval("%s configure -wrap %s", this.id, mode); 267 268 return cast(T) this; 269 } 270 271 /** 272 * Appends text to the widget. 273 * 274 * Params: 275 * text = The text to append. 276 * 277 * Returns: 278 * This widget to aid method chaining. 279 */ 280 public auto appendText(this T)(string text) 281 { 282 // String concatenation is used to build the script here instead of 283 // using format specifiers to enable supporting input which includes 284 // Tcl/Tk reserved characters and elements that could be construed as 285 // format specifiers. 286 string script = std.conv.text(this.id, ` insert end "`, this._tk.escape(text), `"`); 287 this._tk.eval(script); 288 289 return cast(T) this; 290 } 291 292 /** 293 * Inserts text into the widget at a specified line and character index. 294 * 295 * Params: 296 * line = The line at which to insert the text. Indexes start at 1. 297 * character = The character at which to insert the text. Indexes start at 0. 298 * text = The text to insert. 299 * 300 * Returns: 301 * This widget to aid method chaining. 302 */ 303 public auto insertText(this T)(int line, int character, string text) 304 { 305 // String concatenation is used to build the script here instead of 306 // using format specifiers to enable supporting input which includes 307 // Tcl/Tk reserved characters and elements that could be construed as 308 // format specifiers. 309 string script = std.conv.text(this.id, ` insert `, line, `.`, character, ` "`, this._tk.escape(text), `"`); 310 this._tk.eval(script); 311 312 return cast(T) this; 313 } 314 315 /** 316 * Get the text from the widget. 317 * 318 * Returns: 319 * The text from the widget. 320 */ 321 public string getText(this T)() 322 { 323 this._tk.eval("%s get 0.0 end", this.id); 324 325 return this._tk.getResult!(string); 326 } 327 328 /** 329 * Delete text from the widget. 330 * 331 * Params: 332 * fromLine = The line from which to start deleting. Indexes start at 1. 333 * fromChar = The character from which to start deleting. Indexes start at 0. 334 * toLine = The line up to (but not including) which to delete. Indexes start at 1. 335 * toChar = The character up to (but not including) which to delete. Indexes start at 0. 336 * 337 * Returns: 338 * This widget to aid method chaining. 339 */ 340 public auto deleteText(this T)(int fromLine, int fromChar, int toLine, int toChar) 341 { 342 this._tk.eval("%s delete %s.%s %s.%s", this.id, fromLine, fromChar, toLine, toChar); 343 344 return cast(T) this; 345 } 346 347 /** 348 * Delete all content from the widget. 349 * 350 * Returns: 351 * This widget to aid method chaining. 352 */ 353 public auto clear(this T)() 354 { 355 this._tk.eval("%s delete 0.0 end", this.id); 356 357 return cast(T) this; 358 } 359 360 /** 361 * Embed a widget into the text. 362 * 363 * Params: 364 * line = The line at which to insert the text. Indexes start at 1. 365 * character = The character at which to insert the text. Indexes start at 0. 366 * widget = The widget to embed. 367 * padding = The amount of padding around the widget. 368 * 369 * Returns: 370 * This widget to aid method chaining. 371 */ 372 public auto embedWidget(this T)(int line, int character, Widget widget, int padding = 0) 373 { 374 this._tk.eval("%s window create %s.%s -window %s -align center -padx %s -pady %s", this.id, line, character, widget.id, padding, padding); 375 376 return cast(T) this; 377 } 378 379 /** 380 * Embed an image into the text. 381 * 382 * Params: 383 * line = The line at which to insert the text. Indexes start at 1. 384 * character = The character at which to insert the text. Indexes start at 0. 385 * image = The image to embed. 386 * padding = The amount of padding around the widget. 387 * 388 * Returns: 389 * This widget to aid method chaining. 390 */ 391 public auto embedImage(this T)(int line, int character, Image image, int padding = 0) 392 { 393 this._tk.eval("%s image create %s.%s -image %s -align center -padx %s -pady %s", this.id, line, character, image.id, padding, padding); 394 395 return cast(T) this; 396 } 397 398 /** 399 * Undo the last edit to the widget. This only applied to the widget if 400 * undo is enabled. 401 * 402 * Returns: 403 * This widget to aid method chaining. 404 */ 405 public auto undo(this T)() 406 { 407 this._tk.eval("%s edit undo", this.id); 408 409 return cast(T) this; 410 } 411 412 /** 413 * Redo the last edit to the widget. This only applied to the widget if 414 * undo is enabled. 415 * 416 * Returns: 417 * This widget to aid method chaining. 418 */ 419 public auto redo(this T)() 420 { 421 this._tk.eval("%s edit redo", this.id); 422 423 return cast(T) this; 424 } 425 426 /** 427 * Clear all undo's. This only applied to the widget if 428 * undo is enabled. 429 * 430 * Returns: 431 * This widget to aid method chaining. 432 */ 433 public auto resetUndo(this T)() 434 { 435 this._tk.eval("%s edit reset", this.id); 436 437 return cast(T) this; 438 } 439 440 /** 441 * See a particular text index. The text widget automatically scrolls to 442 * see the passed indexes. 443 * 444 * Params: 445 * line = The line to see. Indexes start at 1. 446 * character = The character to see. Indexes start at 0. 447 * 448 * Returns: 449 * This widget to aid method chaining. 450 */ 451 public auto seeText(this T)(int line, int character = 0) 452 { 453 this._tk.eval("%s see %s.%s", this.id, line, character); 454 455 return cast(T) this; 456 } 457 458 /** 459 * Cut the selected text to the clipboard. 460 * 461 * Returns: 462 * This widget to aid method chaining. 463 */ 464 public auto cutText(this T)() 465 { 466 this._tk.eval("tk_textCut %s", this.id); 467 468 return cast(T) this; 469 } 470 471 /** 472 * Copy the selected text to the clipboard. 473 * 474 * Returns: 475 * This widget to aid method chaining. 476 */ 477 public auto copyText(this T)() 478 { 479 this._tk.eval("tk_textCopy %s", this.id); 480 481 return cast(T) this; 482 } 483 484 /** 485 * Paste the selected text from the clipboard at the cursor position. 486 * 487 * Returns: 488 * This widget to aid method chaining. 489 */ 490 public auto pasteText(this T)() 491 { 492 this._tk.eval("tk_textPaste %s", this.id); 493 494 return cast(T) this; 495 } 496 497 /** 498 * Mixin common commands. 499 */ 500 mixin Border; 501 mixin Color; 502 mixin Font; 503 mixin Height; 504 mixin Relief; 505 mixin Width; 506 mixin XScrollCommand!(Text); 507 mixin XView; 508 mixin YScrollCommand!(Text); 509 mixin YView; 510 }