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         this ()
29         {
30             super();
31         }
32     }
33 
34     protected CustomPopupMenuWidget _menu;
35     protected Widget                _selected;
36 
37     ///
38     override @property Widget[] children ()
39     {
40         return _selected? [_selected]: [];
41     }
42 
43     ///
44     override bool handleMouseButton ( MouseButton btn, bool status, vec2 pos )
45     {
46         if ( super.handleMouseButton(btn,status,pos) ) return true;
47 
48         if ( !style.isPointInside( pos ) ) return false;
49         if ( btn == MouseButton.Left && !status ) {
50             openMenu();
51             return true;
52         }
53         return false;
54     }
55 
56     ///
57     override @property const(Cursor) cursor ()
58     {
59         return Cursor.Hand;
60     }
61 
62     ///
63     this ()
64     {
65         super();
66         _menu     = new CustomPopupMenuWidget;
67         _selected = null;
68 
69         parseColorSetsFromFile!"colorset/selectinput.yaml"( style );
70         style.box.borderWidth = Rect(1.pixel);
71         style.box.paddings    = Rect(1.mm);
72         style.box.margins     = Rect(1.mm);
73     }
74 
75     /// Changes selection.
76     void select ( MenuItemWidget s )
77     {
78         _selected = s.child;
79         requestLayout();
80     }
81     /// Opens select menu.
82     void openMenu ()
83     {
84         enforce( _context, "WindowContext is null." );
85 
86         auto size = style.box.borderInsideSize;
87         auto late = style.box.borderInsideLeftTop;
88         late.y   += size.y;
89         late     += style.translate;
90 
91         _context.setPopup( _menu );
92         _menu.move( late, vec2( size.x, 0 ) );
93     }
94 
95     /// Adds an itme.
96     void addItem ( MenuItemWidget i )
97     {
98         i.onPress = () {
99             select( i );
100             return true;
101         };
102         _menu.addItem( i );
103     }
104     /// Removes an item.
105     void removeItem ( MenuItemWidget i )
106     {
107         _menu.removeItem( i );
108     }
109     /// Removes all items.
110     void removeAllItems ()
111     {
112         _menu.removeAllItems();
113     }
114 
115     ///
116     override @property bool trackable () { return true; }
117     ///
118     override @property bool focusable () { return true; }
119 }