1 /** 2 * Widget module. 3 * 4 * License: 5 * MIT. See LICENSE for full details. 6 */ 7 module tkd.widget.notebook; 8 9 /** 10 * Imports. 11 */ 12 import std.array; 13 import tkd.element.uielement; 14 import tkd.image.image; 15 import tkd.image.imageposition; 16 import tkd.widget.common.height; 17 import tkd.widget.common.padding; 18 import tkd.widget.common.width; 19 import tkd.widget.widget; 20 21 /** 22 * A notebook widget manages a collection of panes and displays a single one at 23 * a time. Each pane is associated with a tab, which the user may select to 24 * change the currently-displayed pane. 25 * 26 * Example: 27 * --- 28 * // The notebook must be created first. 29 * // See the constructor notes in the documentation. 30 * auto noteBook = new NoteBook(); 31 * 32 * // The pane's widgets are contained within the frame. 33 * auto pane = new Frame(noteBook); 34 * 35 * noteBook.addTab("Text", pane) 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/height.html, Height) $(BR) 43 * $(LINK2 ./common/padding.html, Padding) $(BR) 44 * $(LINK2 ./common/width.html, Width) $(BR) 45 * ) 46 * 47 * Additional_Events: 48 * Additional events that can also be bound to using the $(LINK2 ../element/uielement.html#UiElement.bind, bind) method. 49 * $(P 50 * <<NotebookTabChanged>>, 51 * <<PrevWindow>>, 52 * <Alt-Key>, 53 * <Button-1>, 54 * <Control-Key-ISO_Left_Tab>, 55 * <Control-Key-Tab>, 56 * <Control-Shift-Key-Tab>, 57 * <Destroy>, 58 * <Key-F10>, 59 * <Key-Left>, 60 * <Key-Right>, 61 * <Key-Tab>, 62 * ) 63 * 64 * See_Also: 65 * $(LINK2 ./widget.html, tkd.widget.widget) 66 */ 67 class NoteBook : Widget 68 { 69 /** 70 * Construct the widget. 71 * 72 * Params: 73 * parent = The parent of this widget. 74 * 75 * Bugs: 76 * Because this widget contains and handles other widget's geometry, it 77 * must be created before the child panes and not chained with methods 78 * that add new tabs. If it is chained, tabs will not be handled 79 * correctly and might not show at all. This seems to be a limitation 80 * with Tcl/Tk. 81 * 82 * See_Also: 83 * $(LINK2 ../element/uielement.html, tkd.element.UiElement) $(BR) 84 */ 85 public this(UiElement parent = null) 86 { 87 super(parent); 88 this._elementId = "notebook"; 89 90 this._tk.eval("ttk::notebook %s", this.id); 91 } 92 93 /** 94 * Add a tab to the notebook. When adding a tab to the notebook the tab 95 * gains an id that is equal to the passed widget's id and can be used 96 * later to refer to the new tab. 97 * 98 * Params: 99 * text = The text of the tab. 100 * widget = The widget to add as the tab pane. 101 * 102 * Returns: 103 * This widget to aid method chaining. 104 */ 105 public auto addTab(this T)(string text, Widget widget) 106 { 107 this.insertTab("end", text, widget); 108 109 return cast(T) this; 110 } 111 112 /** 113 * Insert a tab into the notebook at a specified zero based index. When 114 * adding a tab to the notebook the tab gains an id that is equal to the 115 * passed widget's id and can be used later to refer to the new tab. If the 116 * id of the widget passed is already used as a tab id then that existing 117 * one will be moved to the new position. 118 * 119 * Params: 120 * tabIdentifier = The zero based index or string id of the tab. 121 * text = The text of the tab. 122 * widget = The widget to add as the tab pane. 123 * 124 * Returns: 125 * This widget to aid method chaining. 126 */ 127 public auto insertTab(this T, I)(I tabIdentifier, string text, Widget widget) if (is(I == int) || is(I == string)) 128 { 129 this._tk.eval("%s insert %s %s -text {%s}", this.id, tabIdentifier, widget.id, text); 130 131 return cast(T) this; 132 } 133 134 /** 135 * Select a tab in the notebook. 136 * 137 * Params: 138 * tabIdentifier = The zero based index or string id of the tab. 139 * 140 * Returns: 141 * This widget to aid method chaining. 142 */ 143 public auto selectTab(this T, I)(I tabIdentifier) if (is(I == int) || is(I == string)) 144 { 145 this._tk.eval("%s select %s", this.id, tabIdentifier); 146 147 return cast(T) this; 148 } 149 150 /** 151 * Remove a tab from the notbook. 152 * 153 * Params: 154 * tabIdentifier = The zero based index or string id of the tab. 155 * 156 * Returns: 157 * This widget to aid method chaining. 158 */ 159 public auto removeTab(this T, I)(I tabIdentifier) if (is(I == int) || is(I == string)) 160 { 161 this._tk.eval("%s forget %s", this.id, tabIdentifier); 162 163 return cast(T) this; 164 } 165 166 /** 167 * Hide a tab from the notbook. 168 * 169 * Params: 170 * tabIdentifier = The zero based index or string id of the tab. 171 * 172 * Returns: 173 * This widget to aid method chaining. 174 */ 175 public auto hideTab(this T, I)(I tabIdentifier) if (is(I == int) || is(I == string)) 176 { 177 this._tk.eval("%s hide %s", this.id, tabIdentifier); 178 179 return cast(T) this; 180 } 181 182 /** 183 * Set a tab's state. 184 * 185 * Params: 186 * tabIdentifier = The zero based index or string id of the tab. 187 * state = A widget state. 188 * 189 * Returns: 190 * This widget to aid method chaining. 191 * 192 * See_Also: 193 * $(LINK2 ./state.html, tkd.widget.state) for states. 194 */ 195 public auto setTabState(this T, I)(I tabIdentifier, string state) if (is(I == int) || is(I == string)) 196 { 197 this._tk.eval("%s tab %s -state %s", this.id, tabIdentifier, state); 198 199 return cast(T) this; 200 } 201 202 /** 203 * Set a tab pane's sticky state. Specifies how the slave widget is 204 * positioned within the pane area. Sticky state is a string containing 205 * zero or more of the characters n, s, e, or w. Each letter refers to a 206 * side (north, south, east, or west) that the slave window will "stick" 207 * to, as per the grid geometry manager. 208 * 209 * Params: 210 * tabIdentifier = The zero based index or string id of the tab. 211 * stickyState = A widget state. 212 * 213 * Returns: 214 * This widget to aid method chaining. 215 */ 216 public auto setPaneStickyState(this T, I)(I tabIdentifier, string stickyState) if (is(I == int) || is(I == string)) 217 { 218 this._tk.eval("%s tab %s -sticky %s", this.id, tabIdentifier, stickyState); 219 220 return cast(T) this; 221 } 222 223 /** 224 * Set a tab pane's padding. 225 * 226 * Params: 227 * tabIdentifier = The zero based index or string id of the tab. 228 * padding = The desired widget padding. 229 * 230 * Returns: 231 * This widget to aid method chaining. 232 */ 233 public auto setPanePadding(this T, I)(I tabIdentifier, int padding) if (is(I == int) || is(I == string)) 234 { 235 this._tk.eval("%s tab %s -padding %s", this.id, tabIdentifier, padding); 236 237 return cast(T) this; 238 } 239 240 /** 241 * Set a tab's text. 242 * 243 * Params: 244 * tabIdentifier = The zero based index or string id of the tab. 245 * text = The tab text. 246 * 247 * Returns: 248 * This widget to aid method chaining. 249 */ 250 public auto setTabText(this T, I)(I tabIdentifier, string text) if (is(I == int) || is(I == string)) 251 { 252 this._tk.eval("%s tab %s -text {%s}", this.id, tabIdentifier, text); 253 254 return cast(T) this; 255 } 256 257 /** 258 * Set a tab's image. 259 * 260 * Params: 261 * tabIdentifier = The zero based index or string id of the tab. 262 * image = The image to set on the widget. 263 * imagePosition = The position of the image relative to the text. 264 * 265 * Returns: 266 * This widget to aid method chaining. 267 * 268 * See_Also: 269 * $(LINK2 ../image/image.html, tkd.image.image) $(BR) 270 * $(LINK2 ../image/png.html, tkd.image.png) $(BR) 271 * $(LINK2 ../image/gif.html, tkd.image.gif) $(BR) 272 * $(LINK2 ../image/imageposition.html, tkd.image.imageposition) $(BR) 273 */ 274 public auto setTabImage(this T, I)(I tabIdentifier, Image image, string imagePosition = ImagePosition.image) if (is(I == int) || is(I == string)) 275 { 276 this._tk.eval("%s tab %s -image %s", this.id, tabIdentifier, image.id); 277 this.setTabImagePosition(tabIdentifier, imagePosition); 278 279 return cast(T) this; 280 } 281 282 /** 283 * Change the position of the tab image in relation to the text. 284 * 285 * Params: 286 * tabIdentifier = The zero based index or string id of the tab. 287 * imagePosition = The position of the image relative to the text. 288 * 289 * Returns: 290 * This widget to aid method chaining. 291 * 292 * See_Also: 293 * $(LINK2 ../image/imageposition.html, tkd.image.imageposition) 294 */ 295 public auto setTabImagePosition(this T, I)(I tabIdentifier, string imagePosition) if (is(I == int) || is(I == string)) 296 { 297 this._tk.eval("%s tab %s -compound %s", this.id, tabIdentifier, imagePosition); 298 299 return cast(T) this; 300 } 301 302 /** 303 * Underline a character in the tab text. The underlined character is used 304 * for mnemonic activation if keyboard traversal is enabled. 305 * 306 * Params: 307 * tabIdentifier = The zero based index or string id of the tab. 308 * index = The index of the character to underline. 309 * 310 * Returns: 311 * This widget to aid method chaining. 312 * 313 * See_Also: 314 * $(LINK2 ../image/imageposition.html, tkd.image.imageposition) $(BR) 315 * $(LINK2 ./notebook.html#NoteBook.enableKeyboardTraversal, enableKeyboardTraversal) $(BR) 316 */ 317 public auto underlineTabChar(this T, I)(I tabIdentifier, int index) if (is(I == int) || is(I == string)) 318 { 319 this._tk.eval("%s tab %s -underline %s", this.id, tabIdentifier, index); 320 321 return cast(T) this; 322 } 323 324 /** 325 * Call to enable keyboard traversal of the tabs. 326 * 327 * This will extend the bindings for the toplevel window containing the notebook as follows: 328 * $(UL 329 * $(LI Control-Tab selects the tab following the currently selected one.) 330 * $(LI Control-Shift-Tab selects the tab preceding the currently selected one.) 331 * $(LI Alt-c, where c is the mnemonic (underlined) character of any tab, will select that tab.) 332 * ) 333 * Multiple notebooks in a single window may be enabled for traversal, 334 * including nested notebooks. However, notebook traversal only works 335 * properly if all widget panes are direct children of the notebook. 336 * 337 * Returns: 338 * This widget to aid method chaining. 339 * 340 * See_Also: 341 * $(LINK2 ./notebook.html#NoteBook.underlineTabChar, underlineTabChar) $(BR) 342 */ 343 public auto enableKeyboardTraversal(this T)() 344 { 345 this._tk.eval("ttk::notebook::enableTraversal %s", this.id); 346 347 return cast(T) this; 348 } 349 350 /** 351 * Get an array of all the current tab id's. 352 * 353 * Returns: 354 * An array containing all the tab id's. 355 */ 356 public string[] getTabIds() 357 { 358 this._tk.eval("%s tabs", this.id); 359 return this._tk.getResult!(string).split(); 360 } 361 362 /** 363 * Get the tab index from its id. The id is the widget id that was added as 364 * the tab. 365 * 366 * Params: 367 * tabId = The tab id of the tab. 368 */ 369 public int getTabIndexById(string tabId) 370 { 371 this._tk.eval("%s index %s", this.id, tabId); 372 return this._tk.getResult!(int); 373 } 374 375 /** 376 * Get the number of tabs in the notebook. 377 * 378 * Returns: 379 * The number of tabs. 380 */ 381 public int getNumberOfTabs() 382 { 383 return this.getTabIndexById("end"); 384 } 385 386 /** 387 * Mixin common commands. 388 */ 389 mixin Height; 390 mixin Padding; 391 mixin Width; 392 }