1 // Written in the D programming language. 2 3 /** 4 DLANGUI library. 5 6 This module contains popup widgets implementation. 7 8 9 10 Synopsis: 11 12 ---- 13 import dlangui.widgets.popup; 14 15 ---- 16 17 Copyright: Vadim Lopatin, 2014 18 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 19 Authors: $(WEB coolreader.org, Vadim Lopatin) 20 */ 21 module dlangui.widgets.popup; 22 23 import dlangui.widgets.widget; 24 import dlangui.widgets.layouts; 25 import dlangui.platforms.common.platform; 26 27 /// popup alignment option flags 28 enum PopupAlign : uint { 29 /// center popup around anchor widget center 30 Center = 1, 31 /// place popup below anchor widget close to lower bound 32 Below = 2, 33 /// place popup below anchor widget close to right bound (when no space enough, align near left bound) 34 Right = 4, 35 } 36 37 struct PopupAnchor { 38 Widget widget; 39 uint alignment = PopupAlign.Center; 40 } 41 42 /// popup behavior flags - for PopupWidget.flags property 43 enum PopupFlags : uint { 44 /// close popup when mouse button clicked outside of its bounds 45 CloseOnClickOutside = 1, 46 } 47 48 /// popup widget container 49 class PopupWidget : LinearLayout { 50 protected PopupAnchor _anchor; 51 protected bool _modal; 52 53 protected uint _flags; 54 protected void delegate(PopupWidget popup) _onPopupCloseListener; 55 /// popup close listener (called right before closing) 56 @property void delegate(PopupWidget popup) onPopupCloseListener() { return _onPopupCloseListener; } 57 /// set popup close listener (to call right before closing) 58 @property PopupWidget onPopupCloseListener(void delegate(PopupWidget popup) listener) { _onPopupCloseListener = listener; return this; } 59 60 /// returns popup behavior flags (combination of PopupFlags) 61 @property uint flags() { return _flags; } 62 /// set popup behavior flags (combination of PopupFlags) 63 @property PopupWidget flags(uint flags) { _flags = flags; return this; } 64 65 /// access to popup anchor 66 @property ref PopupAnchor anchor() { return _anchor; } 67 /// returns true if popup is modal 68 bool modal() { return _modal; } 69 /// set modality flag 70 PopupWidget modal(bool modal) { _modal = modal; return this; } 71 72 /// Measure widget according to desired width and height constraints. (Step 1 of two phase layout). 73 override void measure(int parentWidth, int parentHeight) { 74 super.measure(parentWidth, parentHeight); 75 } 76 /// close and destroy popup 77 void close() { 78 window.removePopup(this); 79 } 80 81 /// just call on close listener 82 void onClose() { 83 if (_onPopupCloseListener !is null) 84 _onPopupCloseListener(this); 85 } 86 87 /// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout). 88 override void layout(Rect rc) { 89 if (visibility == Visibility.Gone) { 90 return; 91 } 92 int w = measuredWidth; 93 int h = measuredHeight; 94 if (w > rc.width) 95 w = rc.width; 96 if (h > rc.height) 97 h = rc.height; 98 99 Rect anchorrc; 100 if (anchor.widget !is null) 101 anchorrc = anchor.widget.pos; 102 else 103 anchorrc = rc; 104 105 Rect r; 106 Point anchorPt; 107 108 if (anchor.alignment & PopupAlign.Center) { 109 // center around center of anchor widget 110 r.left = anchorrc.middlex - w / 2; 111 r.top = anchorrc.middley - h / 2; 112 } else if (anchor.alignment & PopupAlign.Below) { 113 r.left = anchorrc.left; 114 r.top = anchorrc.bottom; 115 } else if (anchor.alignment & PopupAlign.Right) { 116 r.left = anchorrc.right; 117 r.top = anchorrc.top; 118 } 119 r.right = r.left + w; 120 r.bottom = r.top + h; 121 r.moveToFit(rc); 122 super.layout(r); 123 } 124 125 this(Widget content, Window window) { 126 _window = window; 127 //styleId = "POPUP_MENU"; 128 addChild(content); 129 } 130 131 /// called for mouse activity outside shown popup bounds 132 bool onMouseEventOutside(MouseEvent event) { 133 if (visibility != Visibility.Visible) 134 return false; 135 if (_flags & PopupFlags.CloseOnClickOutside) { 136 if (event.action == MouseAction.ButtonDown) { 137 // clicked outside - close popup 138 close(); 139 return false; 140 } 141 } 142 return false; 143 } 144 }