1 /// 2 module nanogui.combobox; 3 4 /* 5 NanoGUI was developed by Wenzel Jakob <wenzel.jakob@epfl.ch>. 6 The widget drawing code is based on the NanoVG demo application 7 by Mikko Mononen. 8 9 All rights reserved. Use of this source code is governed by a 10 BSD-style license that can be found in the LICENSE.txt file. 11 */ 12 import std.container.array : Array; 13 import nanogui.popupbutton : PopupButton; 14 import nanogui.button : Button; 15 import nanogui.widget : Widget; 16 import nanogui.common : Vector2i, Vector2f; 17 18 /** 19 * Simple combo box widget based on a popup button. 20 */ 21 class ComboBox : PopupButton 22 { 23 public: 24 /// Create an empty combo box 25 this(Widget parent) 26 { 27 super(parent); 28 mSelectedIndex = 0; 29 } 30 31 /// Create a new combo box with the given items 32 this(Widget parent, const string[] items) 33 { 34 this(parent); 35 this.items(items); 36 } 37 38 /** 39 * Create a new combo box with the given items, providing both short and 40 * long descriptive labels for each item 41 */ 42 this(Widget parent, const string[] items, 43 const string[] itemsShort) 44 { 45 this(parent); 46 this.items(items, itemsShort); 47 } 48 49 /// The callback to execute for this ComboBox. 50 final void delegate(int) callback() const { return mCallback; } 51 52 /// Sets the callback to execute for this ComboBox. 53 final void callback(void delegate(int) callback) { mCallback = callback; } 54 55 /// The current index this ComboBox has selected. 56 final int selectedIndex() const { return mSelectedIndex; } 57 58 /// Sets the current index this ComboBox has selected. 59 final void selectedIndex(int idx) 60 { 61 if (mItemsShort.empty) 62 return; 63 auto children = popup.children; 64 (cast(Button) children[mSelectedIndex]).pushed = false; 65 (cast(Button) children[idx]).pushed = true; 66 mSelectedIndex = idx; 67 caption = mItemsShort[idx]; 68 } 69 70 /// Sets the items for this ComboBox, providing both short and long descriptive lables for each item. 71 final void items(const string[] items, const string[] itemsShort) 72 { 73 import std.exception : enforce; 74 75 enforce(items.length == itemsShort.length); 76 mItems.clear; 77 mItems.insertBack(items); 78 mItemsShort.clear; 79 mItemsShort.insertBack(itemsShort); 80 if (mSelectedIndex < 0 || mSelectedIndex >= cast(int) items.length) 81 mSelectedIndex = 0; 82 while (mPopup.childCount != 0) 83 mPopup.removeChild(mPopup.childCount-1); 84 85 import nanogui.layout : GroupLayout; 86 mPopup.layout = new GroupLayout(2, 2); 87 int index; 88 foreach (const ref str; items) 89 { 90 Button button = new Button(mPopup, str); 91 button.flags = Button.Flags.RadioButton; 92 button.callback = ((int idx) => () { 93 mSelectedIndex = idx; 94 caption = mItemsShort[idx]; 95 pushed = false; 96 popup.visible = false; 97 if (mCallback) 98 mCallback(idx); 99 })(index); 100 index++; 101 } 102 selectedIndex = mSelectedIndex; 103 } 104 105 /// Sets the items for this ComboBox. 106 final void items(const string[] i) { items(i, i); } 107 108 /// The items associated with this ComboBox. 109 final auto items() const { return mItems; } 110 111 /// The short descriptions associated with this ComboBox. 112 final auto itemsShort() const { return mItemsShort; } 113 114 /// Handles mouse scrolling events for this ComboBox. 115 override bool scrollEvent(Vector2i p, Vector2f rel) 116 { 117 import std.algorithm : min, max; 118 119 if (rel.y < 0) 120 { 121 selectedIndex = min(mSelectedIndex+1, cast(int)(items.length-1)); 122 if (mCallback) 123 mCallback(mSelectedIndex); 124 return true; 125 } else if (rel.y > 0) 126 { 127 selectedIndex(max(mSelectedIndex-1, 0)); 128 if (mCallback) 129 mCallback(mSelectedIndex); 130 return true; 131 } 132 return Widget.scrollEvent(p, rel); 133 } 134 135 // /// Saves the state of this ComboBox to the specified Serializer. 136 // virtual void save(Serializer &s) const override; 137 138 // /// Sets the state of this ComboBox from the specified Serializer. 139 // virtual bool load(Serializer &s) override; 140 141 protected: 142 /// The items associated with this ComboBox. 143 Array!string mItems; 144 145 /// The short descriptions of items associated with this ComboBox. 146 Array!string mItemsShort; 147 148 /// The callback for this ComboBox. 149 void delegate(int) mCallback; 150 151 /// The current index this ComboBox has selected. 152 int mSelectedIndex; 153 }