1 module nanogui.popupbutton; 2 /* 3 nanogui/popupbutton.h -- Button which launches a popup widget 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 13 import nanogui.button; 14 import nanogui.popup; 15 import nanogui.entypo; 16 import nanogui.widget; 17 import nanogui.window; 18 import nanogui.common; 19 20 /** 21 * Button which launches a popup widget. 22 * 23 * Remark: 24 * This class overrides `nanogui.Widget.mIconExtraScale`` to be `0.8f`, 25 * which affects all subclasses of this Widget. Subclasses must explicitly 26 * set a different value if needed (e.g., in their constructor). 27 */ 28 class PopupButton : Button 29 { 30 public: 31 this(Widget parent, string caption = "Untitled", 32 int buttonIcon = 0) 33 { 34 super(parent, caption, buttonIcon); 35 36 mChevronIcon = mTheme.mPopupChevronRightIcon; 37 38 flags(Flags.ToggleButton | Flags.PopupButton); 39 40 Window parentWindow = window; 41 mPopup = new Popup(parentWindow.parent, window); 42 mPopup.size(Vector2i(320, 250)); 43 mPopup.visible(false); 44 45 mIconExtraScale = 0.8f;// widget override 46 } 47 48 final void chevronIcon(int icon) { mChevronIcon = icon; } 49 final dchar chevronIcon() const { return mChevronIcon; } 50 51 final void side(Popup.Side popupSide); 52 final Popup.Side side() const { return mPopup.side(); } 53 54 final Popup popup() { return mPopup; } 55 final auto popup() const { return mPopup; } 56 57 override void draw(ref NanoContext ctx) 58 { 59 if (!mEnabled && mPushed) 60 mPushed = false; 61 62 mPopup.visible(mPushed); 63 Button.draw(ctx); 64 65 if (mChevronIcon != dchar.init) 66 { 67 auto icon = mChevronIcon; 68 auto textColor = 69 mTextColor.w == 0 ? mTheme.mTextColor : mTextColor; 70 71 ctx.fontSize((mFontSize < 0 ? mTheme.mButtonFontSize : mFontSize) * icon_scale()); 72 ctx.fontFace("icons"); 73 ctx.fillColor(mEnabled ? textColor : mTheme.mDisabledTextColor); 74 auto algn = NVGTextAlign(); 75 algn.left = true; 76 algn.middle = true; 77 ctx.textAlign(algn); 78 79 float iw = ctx.textBounds(0, 0, [icon], null); 80 auto iconPos = Vector2f(0, mPos.y + mSize.y * 0.5f - 1); 81 82 if (mPopup.side == Popup.Side.Right) 83 iconPos[0] = mPos.x + mSize.x - iw - 8; 84 else 85 iconPos[0] = mPos.x + 8; 86 87 ctx.text(iconPos.x, iconPos.y, [icon]); 88 } 89 } 90 override Vector2i preferredSize(NanoContext ctx) const 91 { 92 return Button.preferredSize(ctx) + Vector2i(15, 0); 93 } 94 override void performLayout(NanoContext ctx) 95 { 96 Widget.performLayout(ctx); 97 98 const Window parentWindow = window; 99 100 int posY = absolutePosition.y - parentWindow.position.y + mSize.y/2; 101 if (mPopup.side == Popup.Side.Right) 102 mPopup.anchorPos(Vector2i(parentWindow.width + 15, posY)); 103 else 104 mPopup.anchorPos(Vector2i(0 - 15, posY)); 105 } 106 107 //virtual void save(Serializer &s) const override; 108 //virtual bool load(Serializer &s) override; 109 protected: 110 Popup mPopup; 111 dchar mChevronIcon; 112 }