1 // Written in the D programming language. 2 /++ 3 + Authors: KanzakiKino 4 + Copyright: KanzakiKino 2018 5 + License: LGPL-3.0 6 ++/ 7 module w4d.widget.input.select; 8 import w4d.parser.colorset, 9 w4d.style.rect, 10 w4d.style.scalar, 11 w4d.task.window, 12 w4d.widget.popup.menu, 13 w4d.widget.base, 14 w4d.widget.panel, 15 w4d.event, 16 w4d.exception; 17 import g4d.glfw.cursor; 18 import gl3n.linalg; 19 20 /// A handler that handles changing selection. 21 alias SelectChanged = EventHandler!( void, int ); 22 23 /// A widget of select input. 24 class SelectInputWidget : PanelWidget 25 { 26 protected class CustomPopupMenuWidget : PopupMenuWidget 27 { 28 override void handlePopup ( bool opened, WindowContext w ) 29 { 30 if ( !opened ) { 31 .SelectInputWidget.requestLayout(); 32 } 33 super.handlePopup( opened, w ); 34 } 35 this () 36 { 37 super(); 38 } 39 } 40 41 protected CustomPopupMenuWidget _menu; 42 protected Widget _selected; 43 44 /// 45 override @property Widget[] children () 46 { 47 return _selected? [_selected]: []; 48 } 49 50 /// 51 override bool handleMouseButton ( MouseButton btn, bool status, vec2 pos ) 52 { 53 if ( super.handleMouseButton(btn,status,pos) ) return true; 54 55 if ( !style.isPointInside( pos ) ) return false; 56 if ( btn == MouseButton.Left && !status ) { 57 openMenu(); 58 return true; 59 } 60 return false; 61 } 62 63 /// 64 override @property const(Cursor) cursor () 65 { 66 return Cursor.Hand; 67 } 68 69 /// 70 this () 71 { 72 super(); 73 _menu = new CustomPopupMenuWidget; 74 _selected = null; 75 76 parseColorSetsFromFile!"colorset/selectinput.yaml"( style ); 77 style.box.borderWidth = Rect(1.pixel); 78 style.box.paddings = Rect(1.mm); 79 style.box.margins = Rect(1.mm); 80 } 81 82 /// Changes selection. 83 void select ( MenuItemWidget s ) 84 { 85 _selected = s.child; 86 requestLayout(); 87 } 88 /// Opens select menu. 89 void openMenu () 90 { 91 enforce( _context, "WindowContext is null." ); 92 93 auto size = style.box.borderInsideSize; 94 auto late = style.box.borderInsideLeftTop; 95 late.y += size.y; 96 late += style.translate; 97 98 _context.setPopup( _menu ); 99 _menu.move( late, vec2( size.x, 0 ) ); 100 } 101 102 /// Adds an itme. 103 void addItem ( MenuItemWidget i ) 104 { 105 i.onPress = () { 106 select( i ); 107 return true; 108 }; 109 _menu.addItem( i ); 110 } 111 /// Removes an item. 112 void removeItem ( MenuItemWidget i ) 113 { 114 _menu.removeItem( i ); 115 } 116 /// Removes all items. 117 void removeAllItems () 118 { 119 _menu.removeAllItems(); 120 } 121 122 /// 123 override @property bool trackable () { return true; } 124 /// 125 override @property bool focusable () { return true; } 126 }