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.Range; 26 27 private import gobject.ObjectG; 28 private import gobject.Signals; 29 private import gtk.Adjustment; 30 private import gtk.OrientableIF; 31 private import gtk.OrientableT; 32 private import gtk.Widget; 33 public import gtkc.gdktypes; 34 private import gtkc.gtk; 35 public import gtkc.gtktypes; 36 private import std.algorithm; 37 38 39 /** 40 * #GtkRange is the common base class for widgets which visualize an 41 * adjustment, e.g #GtkScale or #GtkScrollbar. 42 * 43 * Apart from signals for monitoring the parameters of the adjustment, 44 * #GtkRange provides properties and methods for influencing the sensitivity 45 * of the “steppers”. It also provides properties and methods for setting a 46 * “fill level” on range widgets. See gtk_range_set_fill_level(). 47 */ 48 public class Range : Widget, OrientableIF 49 { 50 /** the main Gtk struct */ 51 protected GtkRange* gtkRange; 52 53 /** Get the main Gtk struct */ 54 public GtkRange* getRangeStruct() 55 { 56 return gtkRange; 57 } 58 59 /** the main Gtk struct as a void* */ 60 protected override void* getStruct() 61 { 62 return cast(void*)gtkRange; 63 } 64 65 protected override void setStruct(GObject* obj) 66 { 67 gtkRange = cast(GtkRange*)obj; 68 super.setStruct(obj); 69 } 70 71 /** 72 * Sets our main struct and passes it to the parent class. 73 */ 74 public this (GtkRange* gtkRange, bool ownedRef = false) 75 { 76 this.gtkRange = gtkRange; 77 super(cast(GtkWidget*)gtkRange, ownedRef); 78 } 79 80 // add the Orientable capabilities 81 mixin OrientableT!(GtkRange); 82 83 84 /** */ 85 public static GType getType() 86 { 87 return gtk_range_get_type(); 88 } 89 90 /** 91 * Get the #GtkAdjustment which is the “model” object for #GtkRange. 92 * See gtk_range_set_adjustment() for details. 93 * The return value does not have a reference added, so should not 94 * be unreferenced. 95 * 96 * Return: a #GtkAdjustment 97 */ 98 public Adjustment getAdjustment() 99 { 100 auto p = gtk_range_get_adjustment(gtkRange); 101 102 if(p is null) 103 { 104 return null; 105 } 106 107 return ObjectG.getDObject!(Adjustment)(cast(GtkAdjustment*) p); 108 } 109 110 /** 111 * Gets the current position of the fill level indicator. 112 * 113 * Return: The current fill level 114 * 115 * Since: 2.12 116 */ 117 public double getFillLevel() 118 { 119 return gtk_range_get_fill_level(gtkRange); 120 } 121 122 /** 123 * Gets the value set by gtk_range_set_flippable(). 124 * 125 * Return: %TRUE if the range is flippable 126 * 127 * Since: 2.18 128 */ 129 public bool getFlippable() 130 { 131 return gtk_range_get_flippable(gtkRange) != 0; 132 } 133 134 /** 135 * Gets the value set by gtk_range_set_inverted(). 136 * 137 * Return: %TRUE if the range is inverted 138 */ 139 public bool getInverted() 140 { 141 return gtk_range_get_inverted(gtkRange) != 0; 142 } 143 144 /** 145 * Gets the sensitivity policy for the stepper that points to the 146 * 'lower' end of the GtkRange’s adjustment. 147 * 148 * Return: The lower stepper’s sensitivity policy. 149 * 150 * Since: 2.10 151 */ 152 public GtkSensitivityType getLowerStepperSensitivity() 153 { 154 return gtk_range_get_lower_stepper_sensitivity(gtkRange); 155 } 156 157 /** 158 * This function is useful mainly for #GtkRange subclasses. 159 * 160 * See gtk_range_set_min_slider_size(). 161 * 162 * Deprecated: Use the min-height/min-width CSS properties on the slider 163 * node. 164 * 165 * Return: The minimum size of the range’s slider. 166 * 167 * Since: 2.20 168 */ 169 public int getMinSliderSize() 170 { 171 return gtk_range_get_min_slider_size(gtkRange); 172 } 173 174 /** 175 * This function returns the area that contains the range’s trough 176 * and its steppers, in widget->window coordinates. 177 * 178 * This function is useful mainly for #GtkRange subclasses. 179 * 180 * Params: 181 * rangeRect = return location for the range rectangle 182 * 183 * Since: 2.20 184 */ 185 public void getRangeRect(out GdkRectangle rangeRect) 186 { 187 gtk_range_get_range_rect(gtkRange, &rangeRect); 188 } 189 190 /** 191 * Gets whether the range is restricted to the fill level. 192 * 193 * Return: %TRUE if @range is restricted to the fill level. 194 * 195 * Since: 2.12 196 */ 197 public bool getRestrictToFillLevel() 198 { 199 return gtk_range_get_restrict_to_fill_level(gtkRange) != 0; 200 } 201 202 /** 203 * Gets the number of digits to round the value to when 204 * it changes. See #GtkRange::change-value. 205 * 206 * Return: the number of digits to round to 207 * 208 * Since: 2.24 209 */ 210 public int getRoundDigits() 211 { 212 return gtk_range_get_round_digits(gtkRange); 213 } 214 215 /** 216 * Gets whether the range displays the fill level graphically. 217 * 218 * Return: %TRUE if @range shows the fill level. 219 * 220 * Since: 2.12 221 */ 222 public bool getShowFillLevel() 223 { 224 return gtk_range_get_show_fill_level(gtkRange) != 0; 225 } 226 227 /** 228 * This function returns sliders range along the long dimension, 229 * in widget->window coordinates. 230 * 231 * This function is useful mainly for #GtkRange subclasses. 232 * 233 * Params: 234 * sliderStart = return location for the slider's 235 * start, or %NULL 236 * sliderEnd = return location for the slider's 237 * end, or %NULL 238 * 239 * Since: 2.20 240 */ 241 public void getSliderRange(out int sliderStart, out int sliderEnd) 242 { 243 gtk_range_get_slider_range(gtkRange, &sliderStart, &sliderEnd); 244 } 245 246 /** 247 * This function is useful mainly for #GtkRange subclasses. 248 * 249 * See gtk_range_set_slider_size_fixed(). 250 * 251 * Return: whether the range’s slider has a fixed size. 252 * 253 * Since: 2.20 254 */ 255 public bool getSliderSizeFixed() 256 { 257 return gtk_range_get_slider_size_fixed(gtkRange) != 0; 258 } 259 260 /** 261 * Gets the sensitivity policy for the stepper that points to the 262 * 'upper' end of the GtkRange’s adjustment. 263 * 264 * Return: The upper stepper’s sensitivity policy. 265 * 266 * Since: 2.10 267 */ 268 public GtkSensitivityType getUpperStepperSensitivity() 269 { 270 return gtk_range_get_upper_stepper_sensitivity(gtkRange); 271 } 272 273 /** 274 * Gets the current value of the range. 275 * 276 * Return: current value of the range. 277 */ 278 public double getValue() 279 { 280 return gtk_range_get_value(gtkRange); 281 } 282 283 /** 284 * Sets the adjustment to be used as the “model” object for this range 285 * widget. The adjustment indicates the current range value, the 286 * minimum and maximum range values, the step/page increments used 287 * for keybindings and scrolling, and the page size. The page size 288 * is normally 0 for #GtkScale and nonzero for #GtkScrollbar, and 289 * indicates the size of the visible area of the widget being scrolled. 290 * The page size affects the size of the scrollbar slider. 291 * 292 * Params: 293 * adjustment = a #GtkAdjustment 294 */ 295 public void setAdjustment(Adjustment adjustment) 296 { 297 gtk_range_set_adjustment(gtkRange, (adjustment is null) ? null : adjustment.getAdjustmentStruct()); 298 } 299 300 /** 301 * Set the new position of the fill level indicator. 302 * 303 * The “fill level” is probably best described by its most prominent 304 * use case, which is an indicator for the amount of pre-buffering in 305 * a streaming media player. In that use case, the value of the range 306 * would indicate the current play position, and the fill level would 307 * be the position up to which the file/stream has been downloaded. 308 * 309 * This amount of prebuffering can be displayed on the range’s trough 310 * and is themeable separately from the trough. To enable fill level 311 * display, use gtk_range_set_show_fill_level(). The range defaults 312 * to not showing the fill level. 313 * 314 * Additionally, it’s possible to restrict the range’s slider position 315 * to values which are smaller than the fill level. This is controller 316 * by gtk_range_set_restrict_to_fill_level() and is by default 317 * enabled. 318 * 319 * Params: 320 * fillLevel = the new position of the fill level indicator 321 * 322 * Since: 2.12 323 */ 324 public void setFillLevel(double fillLevel) 325 { 326 gtk_range_set_fill_level(gtkRange, fillLevel); 327 } 328 329 /** 330 * If a range is flippable, it will switch its direction if it is 331 * horizontal and its direction is %GTK_TEXT_DIR_RTL. 332 * 333 * See gtk_widget_get_direction(). 334 * 335 * Params: 336 * flippable = %TRUE to make the range flippable 337 * 338 * Since: 2.18 339 */ 340 public void setFlippable(bool flippable) 341 { 342 gtk_range_set_flippable(gtkRange, flippable); 343 } 344 345 /** 346 * Sets the step and page sizes for the range. 347 * The step size is used when the user clicks the #GtkScrollbar 348 * arrows or moves #GtkScale via arrow keys. The page size 349 * is used for example when moving via Page Up or Page Down keys. 350 * 351 * Params: 352 * step = step size 353 * page = page size 354 */ 355 public void setIncrements(double step, double page) 356 { 357 gtk_range_set_increments(gtkRange, step, page); 358 } 359 360 /** 361 * Ranges normally move from lower to higher values as the 362 * slider moves from top to bottom or left to right. Inverted 363 * ranges have higher values at the top or on the right rather than 364 * on the bottom or left. 365 * 366 * Params: 367 * setting = %TRUE to invert the range 368 */ 369 public void setInverted(bool setting) 370 { 371 gtk_range_set_inverted(gtkRange, setting); 372 } 373 374 /** 375 * Sets the sensitivity policy for the stepper that points to the 376 * 'lower' end of the GtkRange’s adjustment. 377 * 378 * Params: 379 * sensitivity = the lower stepper’s sensitivity policy. 380 * 381 * Since: 2.10 382 */ 383 public void setLowerStepperSensitivity(GtkSensitivityType sensitivity) 384 { 385 gtk_range_set_lower_stepper_sensitivity(gtkRange, sensitivity); 386 } 387 388 /** 389 * Sets the minimum size of the range’s slider. 390 * 391 * This function is useful mainly for #GtkRange subclasses. 392 * 393 * Deprecated: Use the min-height/min-width CSS properties on the slider 394 * node. 395 * 396 * Params: 397 * minSize = The slider’s minimum size 398 * 399 * Since: 2.20 400 */ 401 public void setMinSliderSize(int minSize) 402 { 403 gtk_range_set_min_slider_size(gtkRange, minSize); 404 } 405 406 /** 407 * Sets the allowable values in the #GtkRange, and clamps the range 408 * value to be between @min and @max. (If the range has a non-zero 409 * page size, it is clamped between @min and @max - page-size.) 410 * 411 * Params: 412 * min = minimum range value 413 * max = maximum range value 414 */ 415 public void setRange(double min, double max) 416 { 417 gtk_range_set_range(gtkRange, min, max); 418 } 419 420 /** 421 * Sets whether the slider is restricted to the fill level. See 422 * gtk_range_set_fill_level() for a general description of the fill 423 * level concept. 424 * 425 * Params: 426 * restrictToFillLevel = Whether the fill level restricts slider movement. 427 * 428 * Since: 2.12 429 */ 430 public void setRestrictToFillLevel(bool restrictToFillLevel) 431 { 432 gtk_range_set_restrict_to_fill_level(gtkRange, restrictToFillLevel); 433 } 434 435 /** 436 * Sets the number of digits to round the value to when 437 * it changes. See #GtkRange::change-value. 438 * 439 * Params: 440 * roundDigits = the precision in digits, or -1 441 * 442 * Since: 2.24 443 */ 444 public void setRoundDigits(int roundDigits) 445 { 446 gtk_range_set_round_digits(gtkRange, roundDigits); 447 } 448 449 /** 450 * Sets whether a graphical fill level is show on the trough. See 451 * gtk_range_set_fill_level() for a general description of the fill 452 * level concept. 453 * 454 * Params: 455 * showFillLevel = Whether a fill level indicator graphics is shown. 456 * 457 * Since: 2.12 458 */ 459 public void setShowFillLevel(bool showFillLevel) 460 { 461 gtk_range_set_show_fill_level(gtkRange, showFillLevel); 462 } 463 464 /** 465 * Sets whether the range’s slider has a fixed size, or a size that 466 * depends on its adjustment’s page size. 467 * 468 * This function is useful mainly for #GtkRange subclasses. 469 * 470 * Params: 471 * sizeFixed = %TRUE to make the slider size constant 472 * 473 * Since: 2.20 474 */ 475 public void setSliderSizeFixed(bool sizeFixed) 476 { 477 gtk_range_set_slider_size_fixed(gtkRange, sizeFixed); 478 } 479 480 /** 481 * Sets the sensitivity policy for the stepper that points to the 482 * 'upper' end of the GtkRange’s adjustment. 483 * 484 * Params: 485 * sensitivity = the upper stepper’s sensitivity policy. 486 * 487 * Since: 2.10 488 */ 489 public void setUpperStepperSensitivity(GtkSensitivityType sensitivity) 490 { 491 gtk_range_set_upper_stepper_sensitivity(gtkRange, sensitivity); 492 } 493 494 /** 495 * Sets the current value of the range; if the value is outside the 496 * minimum or maximum range values, it will be clamped to fit inside 497 * them. The range emits the #GtkRange::value-changed signal if the 498 * value changes. 499 * 500 * Params: 501 * value = new value of the range 502 */ 503 public void setValue(double value) 504 { 505 gtk_range_set_value(gtkRange, value); 506 } 507 508 protected class OnAdjustBoundsDelegateWrapper 509 { 510 void delegate(double, Range) dlg; 511 gulong handlerId; 512 ConnectFlags flags; 513 this(void delegate(double, Range) dlg, gulong handlerId, ConnectFlags flags) 514 { 515 this.dlg = dlg; 516 this.handlerId = handlerId; 517 this.flags = flags; 518 } 519 } 520 protected OnAdjustBoundsDelegateWrapper[] onAdjustBoundsListeners; 521 522 /** 523 * Emitted before clamping a value, to give the application a 524 * chance to adjust the bounds. 525 * 526 * Params: 527 * value = the value before we clamp 528 */ 529 gulong addOnAdjustBounds(void delegate(double, Range) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 530 { 531 onAdjustBoundsListeners ~= new OnAdjustBoundsDelegateWrapper(dlg, 0, connectFlags); 532 onAdjustBoundsListeners[onAdjustBoundsListeners.length - 1].handlerId = Signals.connectData( 533 this, 534 "adjust-bounds", 535 cast(GCallback)&callBackAdjustBounds, 536 cast(void*)onAdjustBoundsListeners[onAdjustBoundsListeners.length - 1], 537 cast(GClosureNotify)&callBackAdjustBoundsDestroy, 538 connectFlags); 539 return onAdjustBoundsListeners[onAdjustBoundsListeners.length - 1].handlerId; 540 } 541 542 extern(C) static void callBackAdjustBounds(GtkRange* rangeStruct, double value,OnAdjustBoundsDelegateWrapper wrapper) 543 { 544 wrapper.dlg(value, wrapper.outer); 545 } 546 547 extern(C) static void callBackAdjustBoundsDestroy(OnAdjustBoundsDelegateWrapper wrapper, GClosure* closure) 548 { 549 wrapper.outer.internalRemoveOnAdjustBounds(wrapper); 550 } 551 552 protected void internalRemoveOnAdjustBounds(OnAdjustBoundsDelegateWrapper source) 553 { 554 foreach(index, wrapper; onAdjustBoundsListeners) 555 { 556 if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId) 557 { 558 onAdjustBoundsListeners[index] = null; 559 onAdjustBoundsListeners = std.algorithm.remove(onAdjustBoundsListeners, index); 560 break; 561 } 562 } 563 } 564 565 566 protected class OnChangeValueDelegateWrapper 567 { 568 bool delegate(GtkScrollType, double, Range) dlg; 569 gulong handlerId; 570 ConnectFlags flags; 571 this(bool delegate(GtkScrollType, double, Range) dlg, gulong handlerId, ConnectFlags flags) 572 { 573 this.dlg = dlg; 574 this.handlerId = handlerId; 575 this.flags = flags; 576 } 577 } 578 protected OnChangeValueDelegateWrapper[] onChangeValueListeners; 579 580 /** 581 * The #GtkRange::change-value signal is emitted when a scroll action is 582 * performed on a range. It allows an application to determine the 583 * type of scroll event that occurred and the resultant new value. 584 * The application can handle the event itself and return %TRUE to 585 * prevent further processing. Or, by returning %FALSE, it can pass 586 * the event to other handlers until the default GTK+ handler is 587 * reached. 588 * 589 * The value parameter is unrounded. An application that overrides 590 * the GtkRange::change-value signal is responsible for clamping the 591 * value to the desired number of decimal digits; the default GTK+ 592 * handler clamps the value based on #GtkRange:round-digits. 593 * 594 * It is not possible to use delayed update policies in an overridden 595 * #GtkRange::change-value handler. 596 * 597 * Params: 598 * scroll = the type of scroll action that was performed 599 * value = the new value resulting from the scroll action 600 * 601 * Return: %TRUE to prevent other handlers from being invoked for 602 * the signal, %FALSE to propagate the signal further 603 * 604 * Since: 2.6 605 */ 606 gulong addOnChangeValue(bool delegate(GtkScrollType, double, Range) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 607 { 608 onChangeValueListeners ~= new OnChangeValueDelegateWrapper(dlg, 0, connectFlags); 609 onChangeValueListeners[onChangeValueListeners.length - 1].handlerId = Signals.connectData( 610 this, 611 "change-value", 612 cast(GCallback)&callBackChangeValue, 613 cast(void*)onChangeValueListeners[onChangeValueListeners.length - 1], 614 cast(GClosureNotify)&callBackChangeValueDestroy, 615 connectFlags); 616 return onChangeValueListeners[onChangeValueListeners.length - 1].handlerId; 617 } 618 619 extern(C) static int callBackChangeValue(GtkRange* rangeStruct, GtkScrollType scroll, double value,OnChangeValueDelegateWrapper wrapper) 620 { 621 return wrapper.dlg(scroll, value, wrapper.outer); 622 } 623 624 extern(C) static void callBackChangeValueDestroy(OnChangeValueDelegateWrapper wrapper, GClosure* closure) 625 { 626 wrapper.outer.internalRemoveOnChangeValue(wrapper); 627 } 628 629 protected void internalRemoveOnChangeValue(OnChangeValueDelegateWrapper source) 630 { 631 foreach(index, wrapper; onChangeValueListeners) 632 { 633 if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId) 634 { 635 onChangeValueListeners[index] = null; 636 onChangeValueListeners = std.algorithm.remove(onChangeValueListeners, index); 637 break; 638 } 639 } 640 } 641 642 643 protected class OnMoveSliderDelegateWrapper 644 { 645 void delegate(GtkScrollType, Range) dlg; 646 gulong handlerId; 647 ConnectFlags flags; 648 this(void delegate(GtkScrollType, Range) dlg, gulong handlerId, ConnectFlags flags) 649 { 650 this.dlg = dlg; 651 this.handlerId = handlerId; 652 this.flags = flags; 653 } 654 } 655 protected OnMoveSliderDelegateWrapper[] onMoveSliderListeners; 656 657 /** 658 * Virtual function that moves the slider. Used for keybindings. 659 * 660 * Params: 661 * step = how to move the slider 662 */ 663 gulong addOnMoveSlider(void delegate(GtkScrollType, Range) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 664 { 665 onMoveSliderListeners ~= new OnMoveSliderDelegateWrapper(dlg, 0, connectFlags); 666 onMoveSliderListeners[onMoveSliderListeners.length - 1].handlerId = Signals.connectData( 667 this, 668 "move-slider", 669 cast(GCallback)&callBackMoveSlider, 670 cast(void*)onMoveSliderListeners[onMoveSliderListeners.length - 1], 671 cast(GClosureNotify)&callBackMoveSliderDestroy, 672 connectFlags); 673 return onMoveSliderListeners[onMoveSliderListeners.length - 1].handlerId; 674 } 675 676 extern(C) static void callBackMoveSlider(GtkRange* rangeStruct, GtkScrollType step,OnMoveSliderDelegateWrapper wrapper) 677 { 678 wrapper.dlg(step, wrapper.outer); 679 } 680 681 extern(C) static void callBackMoveSliderDestroy(OnMoveSliderDelegateWrapper wrapper, GClosure* closure) 682 { 683 wrapper.outer.internalRemoveOnMoveSlider(wrapper); 684 } 685 686 protected void internalRemoveOnMoveSlider(OnMoveSliderDelegateWrapper source) 687 { 688 foreach(index, wrapper; onMoveSliderListeners) 689 { 690 if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId) 691 { 692 onMoveSliderListeners[index] = null; 693 onMoveSliderListeners = std.algorithm.remove(onMoveSliderListeners, index); 694 break; 695 } 696 } 697 } 698 699 700 protected class OnValueChangedDelegateWrapper 701 { 702 void delegate(Range) dlg; 703 gulong handlerId; 704 ConnectFlags flags; 705 this(void delegate(Range) dlg, gulong handlerId, ConnectFlags flags) 706 { 707 this.dlg = dlg; 708 this.handlerId = handlerId; 709 this.flags = flags; 710 } 711 } 712 protected OnValueChangedDelegateWrapper[] onValueChangedListeners; 713 714 /** 715 * Emitted when the range value changes. 716 */ 717 gulong addOnValueChanged(void delegate(Range) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 718 { 719 onValueChangedListeners ~= new OnValueChangedDelegateWrapper(dlg, 0, connectFlags); 720 onValueChangedListeners[onValueChangedListeners.length - 1].handlerId = Signals.connectData( 721 this, 722 "value-changed", 723 cast(GCallback)&callBackValueChanged, 724 cast(void*)onValueChangedListeners[onValueChangedListeners.length - 1], 725 cast(GClosureNotify)&callBackValueChangedDestroy, 726 connectFlags); 727 return onValueChangedListeners[onValueChangedListeners.length - 1].handlerId; 728 } 729 730 extern(C) static void callBackValueChanged(GtkRange* rangeStruct,OnValueChangedDelegateWrapper wrapper) 731 { 732 wrapper.dlg(wrapper.outer); 733 } 734 735 extern(C) static void callBackValueChangedDestroy(OnValueChangedDelegateWrapper wrapper, GClosure* closure) 736 { 737 wrapper.outer.internalRemoveOnValueChanged(wrapper); 738 } 739 740 protected void internalRemoveOnValueChanged(OnValueChangedDelegateWrapper source) 741 { 742 foreach(index, wrapper; onValueChangedListeners) 743 { 744 if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId) 745 { 746 onValueChangedListeners[index] = null; 747 onValueChangedListeners = std.algorithm.remove(onValueChangedListeners, index); 748 break; 749 } 750 } 751 } 752 753 }