1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gtk.EntryCompletion; 26 27 private import glib.ConstructionException; 28 private import glib.Str; 29 private import gobject.ObjectG; 30 private import gobject.Signals; 31 private import gtk.BuildableIF; 32 private import gtk.BuildableT; 33 private import gtk.CellArea; 34 private import gtk.CellLayoutIF; 35 private import gtk.CellLayoutT; 36 private import gtk.TreeIter; 37 private import gtk.TreeModelIF; 38 private import gtk.Widget; 39 private import gtk.c.functions; 40 public import gtk.c.types; 41 public import gtkc.gtktypes; 42 private import std.algorithm; 43 44 45 /** 46 * #GtkEntryCompletion is an auxiliary object to be used in conjunction with 47 * #GtkEntry to provide the completion functionality. It implements the 48 * #GtkCellLayout interface, to allow the user to add extra cells to the 49 * #GtkTreeView with completion matches. 50 * 51 * “Completion functionality” means that when the user modifies the text 52 * in the entry, #GtkEntryCompletion checks which rows in the model match 53 * the current content of the entry, and displays a list of matches. 54 * By default, the matching is done by comparing the entry text 55 * case-insensitively against the text column of the model (see 56 * gtk_entry_completion_set_text_column()), but this can be overridden 57 * with a custom match function (see gtk_entry_completion_set_match_func()). 58 * 59 * When the user selects a completion, the content of the entry is 60 * updated. By default, the content of the entry is replaced by the 61 * text column of the model, but this can be overridden by connecting 62 * to the #GtkEntryCompletion::match-selected signal and updating the 63 * entry in the signal handler. Note that you should return %TRUE from 64 * the signal handler to suppress the default behaviour. 65 * 66 * To add completion functionality to an entry, use gtk_entry_set_completion(). 67 * 68 * In addition to regular completion matches, which will be inserted into the 69 * entry when they are selected, #GtkEntryCompletion also allows to display 70 * “actions” in the popup window. Their appearance is similar to menuitems, 71 * to differentiate them clearly from completion strings. When an action is 72 * selected, the #GtkEntryCompletion::action-activated signal is emitted. 73 * 74 * GtkEntryCompletion uses a #GtkTreeModelFilter model to represent the 75 * subset of the entire model that is currently matching. While the 76 * GtkEntryCompletion signals #GtkEntryCompletion::match-selected and 77 * #GtkEntryCompletion::cursor-on-match take the original model and an 78 * iter pointing to that model as arguments, other callbacks and signals 79 * (such as #GtkCellLayoutDataFuncs or #GtkCellArea::apply-attributes) 80 * will generally take the filter model as argument. As long as you are 81 * only calling gtk_tree_model_get(), this will make no difference to 82 * you. If for some reason, you need the original model, use 83 * gtk_tree_model_filter_get_model(). Don’t forget to use 84 * gtk_tree_model_filter_convert_iter_to_child_iter() to obtain a 85 * matching iter. 86 */ 87 public class EntryCompletion : ObjectG, BuildableIF, CellLayoutIF 88 { 89 /** the main Gtk struct */ 90 protected GtkEntryCompletion* gtkEntryCompletion; 91 92 /** Get the main Gtk struct */ 93 public GtkEntryCompletion* getEntryCompletionStruct(bool transferOwnership = false) 94 { 95 if (transferOwnership) 96 ownedRef = false; 97 return gtkEntryCompletion; 98 } 99 100 /** the main Gtk struct as a void* */ 101 protected override void* getStruct() 102 { 103 return cast(void*)gtkEntryCompletion; 104 } 105 106 /** 107 * Sets our main struct and passes it to the parent class. 108 */ 109 public this (GtkEntryCompletion* gtkEntryCompletion, bool ownedRef = false) 110 { 111 this.gtkEntryCompletion = gtkEntryCompletion; 112 super(cast(GObject*)gtkEntryCompletion, ownedRef); 113 } 114 115 // add the Buildable capabilities 116 mixin BuildableT!(GtkEntryCompletion); 117 118 // add the CellLayout capabilities 119 mixin CellLayoutT!(GtkEntryCompletion); 120 121 122 /** */ 123 public static GType getType() 124 { 125 return gtk_entry_completion_get_type(); 126 } 127 128 /** 129 * Creates a new #GtkEntryCompletion object. 130 * 131 * Returns: A newly created #GtkEntryCompletion object 132 * 133 * Since: 2.4 134 * 135 * Throws: ConstructionException GTK+ fails to create the object. 136 */ 137 public this() 138 { 139 auto p = gtk_entry_completion_new(); 140 141 if(p is null) 142 { 143 throw new ConstructionException("null returned by new"); 144 } 145 146 this(cast(GtkEntryCompletion*) p, true); 147 } 148 149 /** 150 * Creates a new #GtkEntryCompletion object using the 151 * specified @area to layout cells in the underlying 152 * #GtkTreeViewColumn for the drop-down menu. 153 * 154 * Params: 155 * area = the #GtkCellArea used to layout cells 156 * 157 * Returns: A newly created #GtkEntryCompletion object 158 * 159 * Since: 3.0 160 * 161 * Throws: ConstructionException GTK+ fails to create the object. 162 */ 163 public this(CellArea area) 164 { 165 auto p = gtk_entry_completion_new_with_area((area is null) ? null : area.getCellAreaStruct()); 166 167 if(p is null) 168 { 169 throw new ConstructionException("null returned by new_with_area"); 170 } 171 172 this(cast(GtkEntryCompletion*) p, true); 173 } 174 175 /** 176 * Requests a completion operation, or in other words a refiltering of the 177 * current list with completions, using the current key. The completion list 178 * view will be updated accordingly. 179 * 180 * Since: 2.4 181 */ 182 public void complete() 183 { 184 gtk_entry_completion_complete(gtkEntryCompletion); 185 } 186 187 /** 188 * Computes the common prefix that is shared by all rows in @completion 189 * that start with @key. If no row matches @key, %NULL will be returned. 190 * Note that a text column must have been set for this function to work, 191 * see gtk_entry_completion_set_text_column() for details. 192 * 193 * Params: 194 * key = The text to complete for 195 * 196 * Returns: The common prefix all rows starting with 197 * @key or %NULL if no row matches @key. 198 * 199 * Since: 3.4 200 */ 201 public string computePrefix(string key) 202 { 203 auto retStr = gtk_entry_completion_compute_prefix(gtkEntryCompletion, Str.toStringz(key)); 204 205 scope(exit) Str.freeString(retStr); 206 return Str.toString(retStr); 207 } 208 209 /** 210 * Deletes the action at @index_ from @completion’s action list. 211 * 212 * Note that @index_ is a relative position and the position of an 213 * action may have changed since it was inserted. 214 * 215 * Params: 216 * index = the index of the item to delete 217 * 218 * Since: 2.4 219 */ 220 public void deleteAction(int index) 221 { 222 gtk_entry_completion_delete_action(gtkEntryCompletion, index); 223 } 224 225 /** 226 * Get the original text entered by the user that triggered 227 * the completion or %NULL if there’s no completion ongoing. 228 * 229 * Returns: the prefix for the current completion 230 * 231 * Since: 2.12 232 */ 233 public string getCompletionPrefix() 234 { 235 return Str.toString(gtk_entry_completion_get_completion_prefix(gtkEntryCompletion)); 236 } 237 238 /** 239 * Gets the entry @completion has been attached to. 240 * 241 * Returns: The entry @completion has been attached to 242 * 243 * Since: 2.4 244 */ 245 public Widget getEntry() 246 { 247 auto p = gtk_entry_completion_get_entry(gtkEntryCompletion); 248 249 if(p is null) 250 { 251 return null; 252 } 253 254 return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p); 255 } 256 257 /** 258 * Returns whether the common prefix of the possible completions should 259 * be automatically inserted in the entry. 260 * 261 * Returns: %TRUE if inline completion is turned on 262 * 263 * Since: 2.6 264 */ 265 public bool getInlineCompletion() 266 { 267 return gtk_entry_completion_get_inline_completion(gtkEntryCompletion) != 0; 268 } 269 270 /** 271 * Returns %TRUE if inline-selection mode is turned on. 272 * 273 * Returns: %TRUE if inline-selection mode is on 274 * 275 * Since: 2.12 276 */ 277 public bool getInlineSelection() 278 { 279 return gtk_entry_completion_get_inline_selection(gtkEntryCompletion) != 0; 280 } 281 282 /** 283 * Returns the minimum key length as set for @completion. 284 * 285 * Returns: The currently used minimum key length 286 * 287 * Since: 2.4 288 */ 289 public int getMinimumKeyLength() 290 { 291 return gtk_entry_completion_get_minimum_key_length(gtkEntryCompletion); 292 } 293 294 /** 295 * Returns the model the #GtkEntryCompletion is using as data source. 296 * Returns %NULL if the model is unset. 297 * 298 * Returns: A #GtkTreeModel, or %NULL if none 299 * is currently being used 300 * 301 * Since: 2.4 302 */ 303 public TreeModelIF getModel() 304 { 305 auto p = gtk_entry_completion_get_model(gtkEntryCompletion); 306 307 if(p is null) 308 { 309 return null; 310 } 311 312 return ObjectG.getDObject!(TreeModelIF)(cast(GtkTreeModel*) p); 313 } 314 315 /** 316 * Returns whether the completions should be presented in a popup window. 317 * 318 * Returns: %TRUE if popup completion is turned on 319 * 320 * Since: 2.6 321 */ 322 public bool getPopupCompletion() 323 { 324 return gtk_entry_completion_get_popup_completion(gtkEntryCompletion) != 0; 325 } 326 327 /** 328 * Returns whether the completion popup window will be resized to the 329 * width of the entry. 330 * 331 * Returns: %TRUE if the popup window will be resized to the width of 332 * the entry 333 * 334 * Since: 2.8 335 */ 336 public bool getPopupSetWidth() 337 { 338 return gtk_entry_completion_get_popup_set_width(gtkEntryCompletion) != 0; 339 } 340 341 /** 342 * Returns whether the completion popup window will appear even if there is 343 * only a single match. 344 * 345 * Returns: %TRUE if the popup window will appear regardless of the 346 * number of matches 347 * 348 * Since: 2.8 349 */ 350 public bool getPopupSingleMatch() 351 { 352 return gtk_entry_completion_get_popup_single_match(gtkEntryCompletion) != 0; 353 } 354 355 /** 356 * Returns the column in the model of @completion to get strings from. 357 * 358 * Returns: the column containing the strings 359 * 360 * Since: 2.6 361 */ 362 public int getTextColumn() 363 { 364 return gtk_entry_completion_get_text_column(gtkEntryCompletion); 365 } 366 367 /** 368 * Inserts an action in @completion’s action item list at position @index_ 369 * with markup @markup. 370 * 371 * Params: 372 * index = the index of the item to insert 373 * markup = markup of the item to insert 374 * 375 * Since: 2.4 376 */ 377 public void insertActionMarkup(int index, string markup) 378 { 379 gtk_entry_completion_insert_action_markup(gtkEntryCompletion, index, Str.toStringz(markup)); 380 } 381 382 /** 383 * Inserts an action in @completion’s action item list at position @index_ 384 * with text @text. If you want the action item to have markup, use 385 * gtk_entry_completion_insert_action_markup(). 386 * 387 * Note that @index_ is a relative position in the list of actions and 388 * the position of an action can change when deleting a different action. 389 * 390 * Params: 391 * index = the index of the item to insert 392 * text = text of the item to insert 393 * 394 * Since: 2.4 395 */ 396 public void insertActionText(int index, string text) 397 { 398 gtk_entry_completion_insert_action_text(gtkEntryCompletion, index, Str.toStringz(text)); 399 } 400 401 /** 402 * Requests a prefix insertion. 403 * 404 * Since: 2.6 405 */ 406 public void insertPrefix() 407 { 408 gtk_entry_completion_insert_prefix(gtkEntryCompletion); 409 } 410 411 /** 412 * Sets whether the common prefix of the possible completions should 413 * be automatically inserted in the entry. 414 * 415 * Params: 416 * inlineCompletion = %TRUE to do inline completion 417 * 418 * Since: 2.6 419 */ 420 public void setInlineCompletion(bool inlineCompletion) 421 { 422 gtk_entry_completion_set_inline_completion(gtkEntryCompletion, inlineCompletion); 423 } 424 425 /** 426 * Sets whether it is possible to cycle through the possible completions 427 * inside the entry. 428 * 429 * Params: 430 * inlineSelection = %TRUE to do inline selection 431 * 432 * Since: 2.12 433 */ 434 public void setInlineSelection(bool inlineSelection) 435 { 436 gtk_entry_completion_set_inline_selection(gtkEntryCompletion, inlineSelection); 437 } 438 439 /** 440 * Sets the match function for @completion to be @func. The match function 441 * is used to determine if a row should or should not be in the completion 442 * list. 443 * 444 * Params: 445 * func = the #GtkEntryCompletionMatchFunc to use 446 * funcData = user data for @func 447 * funcNotify = destroy notify for @func_data. 448 * 449 * Since: 2.4 450 */ 451 public void setMatchFunc(GtkEntryCompletionMatchFunc func, void* funcData, GDestroyNotify funcNotify) 452 { 453 gtk_entry_completion_set_match_func(gtkEntryCompletion, func, funcData, funcNotify); 454 } 455 456 /** 457 * Requires the length of the search key for @completion to be at least 458 * @length. This is useful for long lists, where completing using a small 459 * key takes a lot of time and will come up with meaningless results anyway 460 * (ie, a too large dataset). 461 * 462 * Params: 463 * length = the minimum length of the key in order to start completing 464 * 465 * Since: 2.4 466 */ 467 public void setMinimumKeyLength(int length) 468 { 469 gtk_entry_completion_set_minimum_key_length(gtkEntryCompletion, length); 470 } 471 472 /** 473 * Sets the model for a #GtkEntryCompletion. If @completion already has 474 * a model set, it will remove it before setting the new model. 475 * If model is %NULL, then it will unset the model. 476 * 477 * Params: 478 * model = the #GtkTreeModel 479 * 480 * Since: 2.4 481 */ 482 public void setModel(TreeModelIF model) 483 { 484 gtk_entry_completion_set_model(gtkEntryCompletion, (model is null) ? null : model.getTreeModelStruct()); 485 } 486 487 /** 488 * Sets whether the completions should be presented in a popup window. 489 * 490 * Params: 491 * popupCompletion = %TRUE to do popup completion 492 * 493 * Since: 2.6 494 */ 495 public void setPopupCompletion(bool popupCompletion) 496 { 497 gtk_entry_completion_set_popup_completion(gtkEntryCompletion, popupCompletion); 498 } 499 500 /** 501 * Sets whether the completion popup window will be resized to be the same 502 * width as the entry. 503 * 504 * Params: 505 * popupSetWidth = %TRUE to make the width of the popup the same as the entry 506 * 507 * Since: 2.8 508 */ 509 public void setPopupSetWidth(bool popupSetWidth) 510 { 511 gtk_entry_completion_set_popup_set_width(gtkEntryCompletion, popupSetWidth); 512 } 513 514 /** 515 * Sets whether the completion popup window will appear even if there is 516 * only a single match. You may want to set this to %FALSE if you 517 * are using [inline completion][GtkEntryCompletion--inline-completion]. 518 * 519 * Params: 520 * popupSingleMatch = %TRUE if the popup should appear even for a single 521 * match 522 * 523 * Since: 2.8 524 */ 525 public void setPopupSingleMatch(bool popupSingleMatch) 526 { 527 gtk_entry_completion_set_popup_single_match(gtkEntryCompletion, popupSingleMatch); 528 } 529 530 /** 531 * Convenience function for setting up the most used case of this code: a 532 * completion list with just strings. This function will set up @completion 533 * to have a list displaying all (and just) strings in the completion list, 534 * and to get those strings from @column in the model of @completion. 535 * 536 * This functions creates and adds a #GtkCellRendererText for the selected 537 * column. If you need to set the text column, but don't want the cell 538 * renderer, use g_object_set() to set the #GtkEntryCompletion:text-column 539 * property directly. 540 * 541 * Params: 542 * column = the column in the model of @completion to get strings from 543 * 544 * Since: 2.4 545 */ 546 public void setTextColumn(int column) 547 { 548 gtk_entry_completion_set_text_column(gtkEntryCompletion, column); 549 } 550 551 protected class OnActionActivatedDelegateWrapper 552 { 553 void delegate(int, EntryCompletion) dlg; 554 gulong handlerId; 555 556 this(void delegate(int, EntryCompletion) dlg) 557 { 558 this.dlg = dlg; 559 onActionActivatedListeners ~= this; 560 } 561 562 void remove(OnActionActivatedDelegateWrapper source) 563 { 564 foreach(index, wrapper; onActionActivatedListeners) 565 { 566 if (wrapper.handlerId == source.handlerId) 567 { 568 onActionActivatedListeners[index] = null; 569 onActionActivatedListeners = std.algorithm.remove(onActionActivatedListeners, index); 570 break; 571 } 572 } 573 } 574 } 575 OnActionActivatedDelegateWrapper[] onActionActivatedListeners; 576 577 /** 578 * Gets emitted when an action is activated. 579 * 580 * Params: 581 * index = the index of the activated action 582 * 583 * Since: 2.4 584 */ 585 gulong addOnActionActivated(void delegate(int, EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 586 { 587 auto wrapper = new OnActionActivatedDelegateWrapper(dlg); 588 wrapper.handlerId = Signals.connectData( 589 this, 590 "action-activated", 591 cast(GCallback)&callBackActionActivated, 592 cast(void*)wrapper, 593 cast(GClosureNotify)&callBackActionActivatedDestroy, 594 connectFlags); 595 return wrapper.handlerId; 596 } 597 598 extern(C) static void callBackActionActivated(GtkEntryCompletion* entrycompletionStruct, int index, OnActionActivatedDelegateWrapper wrapper) 599 { 600 wrapper.dlg(index, wrapper.outer); 601 } 602 603 extern(C) static void callBackActionActivatedDestroy(OnActionActivatedDelegateWrapper wrapper, GClosure* closure) 604 { 605 wrapper.remove(wrapper); 606 } 607 608 protected class OnCursorOnMatchDelegateWrapper 609 { 610 bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg; 611 gulong handlerId; 612 613 this(bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg) 614 { 615 this.dlg = dlg; 616 onCursorOnMatchListeners ~= this; 617 } 618 619 void remove(OnCursorOnMatchDelegateWrapper source) 620 { 621 foreach(index, wrapper; onCursorOnMatchListeners) 622 { 623 if (wrapper.handlerId == source.handlerId) 624 { 625 onCursorOnMatchListeners[index] = null; 626 onCursorOnMatchListeners = std.algorithm.remove(onCursorOnMatchListeners, index); 627 break; 628 } 629 } 630 } 631 } 632 OnCursorOnMatchDelegateWrapper[] onCursorOnMatchListeners; 633 634 /** 635 * Gets emitted when a match from the cursor is on a match 636 * of the list. The default behaviour is to replace the contents 637 * of the entry with the contents of the text column in the row 638 * pointed to by @iter. 639 * 640 * Note that @model is the model that was passed to 641 * gtk_entry_completion_set_model(). 642 * 643 * Params: 644 * model = the #GtkTreeModel containing the matches 645 * iter = a #GtkTreeIter positioned at the selected match 646 * 647 * Returns: %TRUE if the signal has been handled 648 * 649 * Since: 2.12 650 */ 651 gulong addOnCursorOnMatch(bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 652 { 653 auto wrapper = new OnCursorOnMatchDelegateWrapper(dlg); 654 wrapper.handlerId = Signals.connectData( 655 this, 656 "cursor-on-match", 657 cast(GCallback)&callBackCursorOnMatch, 658 cast(void*)wrapper, 659 cast(GClosureNotify)&callBackCursorOnMatchDestroy, 660 connectFlags); 661 return wrapper.handlerId; 662 } 663 664 extern(C) static int callBackCursorOnMatch(GtkEntryCompletion* entrycompletionStruct, GtkTreeModel* model, GtkTreeIter* iter, OnCursorOnMatchDelegateWrapper wrapper) 665 { 666 return wrapper.dlg(ObjectG.getDObject!(TreeModelIF)(model), ObjectG.getDObject!(TreeIter)(iter), wrapper.outer); 667 } 668 669 extern(C) static void callBackCursorOnMatchDestroy(OnCursorOnMatchDelegateWrapper wrapper, GClosure* closure) 670 { 671 wrapper.remove(wrapper); 672 } 673 674 protected class OnInsertPrefixDelegateWrapper 675 { 676 bool delegate(string, EntryCompletion) dlg; 677 gulong handlerId; 678 679 this(bool delegate(string, EntryCompletion) dlg) 680 { 681 this.dlg = dlg; 682 onInsertPrefixListeners ~= this; 683 } 684 685 void remove(OnInsertPrefixDelegateWrapper source) 686 { 687 foreach(index, wrapper; onInsertPrefixListeners) 688 { 689 if (wrapper.handlerId == source.handlerId) 690 { 691 onInsertPrefixListeners[index] = null; 692 onInsertPrefixListeners = std.algorithm.remove(onInsertPrefixListeners, index); 693 break; 694 } 695 } 696 } 697 } 698 OnInsertPrefixDelegateWrapper[] onInsertPrefixListeners; 699 700 /** 701 * Gets emitted when the inline autocompletion is triggered. 702 * The default behaviour is to make the entry display the 703 * whole prefix and select the newly inserted part. 704 * 705 * Applications may connect to this signal in order to insert only a 706 * smaller part of the @prefix into the entry - e.g. the entry used in 707 * the #GtkFileChooser inserts only the part of the prefix up to the 708 * next '/'. 709 * 710 * Params: 711 * prefix = the common prefix of all possible completions 712 * 713 * Returns: %TRUE if the signal has been handled 714 * 715 * Since: 2.6 716 */ 717 gulong addOnInsertPrefix(bool delegate(string, EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 718 { 719 auto wrapper = new OnInsertPrefixDelegateWrapper(dlg); 720 wrapper.handlerId = Signals.connectData( 721 this, 722 "insert-prefix", 723 cast(GCallback)&callBackInsertPrefix, 724 cast(void*)wrapper, 725 cast(GClosureNotify)&callBackInsertPrefixDestroy, 726 connectFlags); 727 return wrapper.handlerId; 728 } 729 730 extern(C) static int callBackInsertPrefix(GtkEntryCompletion* entrycompletionStruct, char* prefix, OnInsertPrefixDelegateWrapper wrapper) 731 { 732 return wrapper.dlg(Str.toString(prefix), wrapper.outer); 733 } 734 735 extern(C) static void callBackInsertPrefixDestroy(OnInsertPrefixDelegateWrapper wrapper, GClosure* closure) 736 { 737 wrapper.remove(wrapper); 738 } 739 740 protected class OnMatchSelectedDelegateWrapper 741 { 742 bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg; 743 gulong handlerId; 744 745 this(bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg) 746 { 747 this.dlg = dlg; 748 onMatchSelectedListeners ~= this; 749 } 750 751 void remove(OnMatchSelectedDelegateWrapper source) 752 { 753 foreach(index, wrapper; onMatchSelectedListeners) 754 { 755 if (wrapper.handlerId == source.handlerId) 756 { 757 onMatchSelectedListeners[index] = null; 758 onMatchSelectedListeners = std.algorithm.remove(onMatchSelectedListeners, index); 759 break; 760 } 761 } 762 } 763 } 764 OnMatchSelectedDelegateWrapper[] onMatchSelectedListeners; 765 766 /** 767 * Gets emitted when a match from the list is selected. 768 * The default behaviour is to replace the contents of the 769 * entry with the contents of the text column in the row 770 * pointed to by @iter. 771 * 772 * Note that @model is the model that was passed to 773 * gtk_entry_completion_set_model(). 774 * 775 * Params: 776 * model = the #GtkTreeModel containing the matches 777 * iter = a #GtkTreeIter positioned at the selected match 778 * 779 * Returns: %TRUE if the signal has been handled 780 * 781 * Since: 2.4 782 */ 783 gulong addOnMatchSelected(bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 784 { 785 auto wrapper = new OnMatchSelectedDelegateWrapper(dlg); 786 wrapper.handlerId = Signals.connectData( 787 this, 788 "match-selected", 789 cast(GCallback)&callBackMatchSelected, 790 cast(void*)wrapper, 791 cast(GClosureNotify)&callBackMatchSelectedDestroy, 792 connectFlags); 793 return wrapper.handlerId; 794 } 795 796 extern(C) static int callBackMatchSelected(GtkEntryCompletion* entrycompletionStruct, GtkTreeModel* model, GtkTreeIter* iter, OnMatchSelectedDelegateWrapper wrapper) 797 { 798 return wrapper.dlg(ObjectG.getDObject!(TreeModelIF)(model), ObjectG.getDObject!(TreeIter)(iter), wrapper.outer); 799 } 800 801 extern(C) static void callBackMatchSelectedDestroy(OnMatchSelectedDelegateWrapper wrapper, GClosure* closure) 802 { 803 wrapper.remove(wrapper); 804 } 805 806 protected class OnNoMatchesDelegateWrapper 807 { 808 void delegate(EntryCompletion) dlg; 809 gulong handlerId; 810 811 this(void delegate(EntryCompletion) dlg) 812 { 813 this.dlg = dlg; 814 onNoMatchesListeners ~= this; 815 } 816 817 void remove(OnNoMatchesDelegateWrapper source) 818 { 819 foreach(index, wrapper; onNoMatchesListeners) 820 { 821 if (wrapper.handlerId == source.handlerId) 822 { 823 onNoMatchesListeners[index] = null; 824 onNoMatchesListeners = std.algorithm.remove(onNoMatchesListeners, index); 825 break; 826 } 827 } 828 } 829 } 830 OnNoMatchesDelegateWrapper[] onNoMatchesListeners; 831 832 /** 833 * Gets emitted when the filter model has zero 834 * number of rows in completion_complete method. 835 * (In other words when GtkEntryCompletion is out of 836 * suggestions) 837 * 838 * Since: 3.14 839 */ 840 gulong addOnNoMatches(void delegate(EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 841 { 842 auto wrapper = new OnNoMatchesDelegateWrapper(dlg); 843 wrapper.handlerId = Signals.connectData( 844 this, 845 "no-matches", 846 cast(GCallback)&callBackNoMatches, 847 cast(void*)wrapper, 848 cast(GClosureNotify)&callBackNoMatchesDestroy, 849 connectFlags); 850 return wrapper.handlerId; 851 } 852 853 extern(C) static void callBackNoMatches(GtkEntryCompletion* entrycompletionStruct, OnNoMatchesDelegateWrapper wrapper) 854 { 855 wrapper.dlg(wrapper.outer); 856 } 857 858 extern(C) static void callBackNoMatchesDestroy(OnNoMatchesDelegateWrapper wrapper, GClosure* closure) 859 { 860 wrapper.remove(wrapper); 861 } 862 }