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