DarkComboBox.bf 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. using System;
  2. using System.Collections;
  3. using System.Text;
  4. using Beefy.widgets;
  5. using Beefy.gfx;
  6. using Beefy.events;
  7. namespace Beefy.theme.dark
  8. {
  9. public class DarkComboBox : ComboBox
  10. {
  11. public class CBMenuWidget : DarkMenuWidget
  12. {
  13. public this(Menu menu) :
  14. base(menu)
  15. {
  16. }
  17. public override float GetReverseAdjust()
  18. {
  19. return GS!(-10);
  20. }
  21. }
  22. /*public string Label
  23. {
  24. get
  25. {
  26. if (mEditWidget == null)
  27. return mLabel;
  28. else
  29. return mEditWidget.Text;
  30. }
  31. set
  32. {
  33. if (mEditWidget == null)
  34. mLabel = value;
  35. else
  36. mEditWidget.Text = value;
  37. }
  38. }*/
  39. public enum FrameKind
  40. {
  41. OnWindow,
  42. Frameless,
  43. Transparent
  44. }
  45. String mLabel ~ delete _;
  46. public float mLabelX = GS!(8);
  47. public FontAlign mLabelAlign = FontAlign.Centered;
  48. public FrameKind mFrameKind = .OnWindow;
  49. public Event<Action<Menu>> mPopulateMenuAction ~ _.Dispose();
  50. public CBMenuWidget mCurMenuWidget;
  51. bool mJustClosed;
  52. public uint32 mBkgColor;
  53. public DarkEditWidget mEditWidget;
  54. bool mAllowReverseDropdown; // Allow popdown to "popup" if there isn't enough space
  55. public Widget mPrevFocusWidget;
  56. public bool mFocusDropdown = true;
  57. virtual public StringView Label
  58. {
  59. get
  60. {
  61. if (mEditWidget != null)
  62. {
  63. if (mLabel == null)
  64. mLabel = new String();
  65. mLabel.Clear();
  66. mEditWidget.GetText(mLabel);
  67. }
  68. return mLabel;
  69. }
  70. set
  71. {
  72. String.NewOrSet!(mLabel, value);
  73. if (mEditWidget != null)
  74. mEditWidget.SetText(mLabel);
  75. }
  76. }
  77. public override void Draw(Graphics g)
  78. {
  79. base.Draw(g);
  80. float yOfs = 0;
  81. if (mEditWidget != null)
  82. {
  83. g.DrawBox(DarkTheme.sDarkTheme.GetImage(.EditBox), 0, 0, mWidth, mHeight);
  84. g.Draw(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.ComboEnd], mWidth - GS!(25), (mHeight - GS!(22)) / 2 + yOfs);
  85. if ((mHasFocus) || (mEditWidget.mHasFocus))
  86. {
  87. using (g.PushColor(DarkTheme.COLOR_SELECTED_OUTLINE))
  88. g.DrawBox(DarkTheme.sDarkTheme.GetImage(.Outline), 0, 0, mWidth, mHeight);
  89. }
  90. return;
  91. }
  92. if ((mFrameKind == .OnWindow) || (mFrameKind == .Frameless))
  93. {
  94. Image texture = DarkTheme.sDarkTheme.mImages[(mFrameKind == .OnWindow) ? (int32)DarkTheme.ImageIdx.ComboBox : (int32)DarkTheme.ImageIdx.ComboBoxFrameless];
  95. g.DrawBox(texture, 0, GS!(-2), mWidth, mHeight);
  96. }
  97. else
  98. {
  99. if (mBkgColor != 0)
  100. {
  101. using (g.PushColor(mBkgColor))
  102. g.FillRect(0, 0, mWidth, mHeight);
  103. }
  104. yOfs = 2.0f;
  105. }
  106. if (mEditWidget == null)
  107. {
  108. using (g.PushColor(mDisabled ? 0x80FFFFFF : Color.White))
  109. {
  110. g.Draw(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.ComboEnd], mWidth - GS!(25), (mHeight - GS!(24)) / 2 + yOfs);
  111. g.SetFont(DarkTheme.sDarkTheme.mSmallFont);
  112. String label = scope String();
  113. GetLabel(label);
  114. if (label != null)
  115. {
  116. float fontHeight = g.mFont.GetHeight();
  117. //g.DrawString(label, mLabelX, (mHeight - GS!(24)) / 2, mLabelAlign, mWidth - mLabelX - GS!(24), FontOverflowMode.Ellipsis);
  118. g.DrawString(label, mLabelX, (mHeight - fontHeight) / 2 - (int)GS!(3.5f), mLabelAlign, mWidth - mLabelX - GS!(24), FontOverflowMode.Ellipsis);
  119. }
  120. }
  121. if (mHasFocus)
  122. {
  123. using (g.PushColor(DarkTheme.COLOR_SELECTED_OUTLINE))
  124. g.DrawBox(DarkTheme.sDarkTheme.GetImage(.Outline), GS!(2), 0, mWidth - GS!(4), mHeight - GS!(4));
  125. }
  126. }
  127. /*using (g.PushColor(0x1FFF0000))
  128. g.FillRect(0, 0, mWidth, mHeight);*/
  129. }
  130. public void GetLabel(String label)
  131. {
  132. if (mEditWidget == null)
  133. {
  134. if (mLabel != null)
  135. label.Append(mLabel);
  136. }
  137. else
  138. mEditWidget.GetText(label);
  139. }
  140. void HandleKeyDown(KeyDownEvent evt)
  141. {
  142. if (evt.mKeyCode == KeyCode.Escape)
  143. {
  144. evt.mHandled = true;
  145. mCurMenuWidget.Close();
  146. }
  147. }
  148. public virtual void MenuClosed()
  149. {
  150. if (mPrevFocusWidget != null)
  151. {
  152. mPrevFocusWidget.SetFocus();
  153. }
  154. }
  155. void HandleClose(Menu menu, Menu selectedItem)
  156. {
  157. mCurMenuWidget = null;
  158. mJustClosed = true;
  159. //mWidgetWindow.mWindowKeyDownDelegate -= HandleKeyDown;
  160. MenuClosed();
  161. }
  162. public virtual MenuWidget ShowDropdown()
  163. {
  164. mPrevFocusWidget = mWidgetWindow.mFocusWidget;
  165. float popupXOfs = GS!(5);
  166. float popupYOfs = GS!(-2);
  167. if (mEditWidget != null)
  168. {
  169. popupXOfs = GS!(2);
  170. popupYOfs = GS!(2);
  171. }
  172. else if (mFrameKind == .Transparent)
  173. {
  174. popupXOfs = GS!(2);
  175. popupYOfs = GS!(2);
  176. }
  177. //if (mCurMenuWidget != null)
  178. //mCurMenuWidget.Close();
  179. mAutoFocus = false;
  180. Menu aMenu = new Menu();
  181. mPopulateMenuAction(aMenu);
  182. WidgetWindow menuWindow = null;
  183. if (mCurMenuWidget != null)
  184. menuWindow = mCurMenuWidget.mWidgetWindow;
  185. let menuWidget = new CBMenuWidget(aMenu);
  186. //menuWidget.SetShowPct(0.0f);
  187. //menuWidget.mWindowFlags &= ~(BFWindow.Flags.PopupPosition);
  188. mCurMenuWidget = menuWidget;
  189. aMenu.mOnMenuClosed.Add(new => HandleClose);
  190. menuWidget.mMinContainerWidth = mWidth + GS!(8);
  191. menuWidget.mMaxContainerWidth = Math.Max(menuWidget.mMinContainerWidth, 1536);
  192. menuWidget.mWindowFlags = .ClientSized | .DestAlpha | .FakeFocus;
  193. if (!mFocusDropdown)
  194. menuWidget.mWindowFlags |= .NoActivate;
  195. menuWidget.CalcSize();
  196. float popupY = mHeight + popupYOfs;
  197. //TODO: Autocomplete didn't work on this: BFApp.sApp.GetW...
  198. menuWidget.Init(this, popupXOfs, popupY, true, menuWindow);
  199. // Why were we capturing?
  200. mWidgetWindow.TransferMouse(menuWidget.mWidgetWindow);
  201. if (menuWindow == null)
  202. menuWidget.SetShowPct(0.0f);
  203. return menuWidget;
  204. }
  205. public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
  206. {
  207. base.MouseDown(x, y, btn, btnCount);
  208. if (mDisabled)
  209. return;
  210. if ((mCurMenuWidget == null) && (!mJustClosed))
  211. {
  212. if (mEditWidget != null)
  213. SetFocus();
  214. ShowDropdown();
  215. //mCurMenuWidget.SetFocus();
  216. //mWidgetWindow.mWindowKeyDownDelegate += HandleKeyDown;
  217. }
  218. }
  219. public override void SetFocus()
  220. {
  221. if (mEditWidget != null)
  222. {
  223. mEditWidget.SetFocus();
  224. return;
  225. }
  226. base.SetFocus();
  227. }
  228. public override void Update()
  229. {
  230. base.Update();
  231. mJustClosed = false;
  232. bool hasFocus = mHasFocus;
  233. if ((mEditWidget != null) && (mEditWidget.mHasFocus))
  234. hasFocus = true;
  235. if ((!hasFocus) && (mCurMenuWidget != null))
  236. if (mCurMenuWidget.mWidgetWindow.mHasFocus)
  237. hasFocus = true;
  238. if ((!hasFocus) && (mCurMenuWidget != null))
  239. {
  240. mCurMenuWidget.SubmitSelection();
  241. if (mCurMenuWidget != null)
  242. mCurMenuWidget.Close();
  243. }
  244. }
  245. public override void Resize(float x, float y, float width, float height)
  246. {
  247. base.Resize(x, y, width, height);
  248. ResizeComponents();
  249. }
  250. private void ResizeComponents()
  251. {
  252. if (mEditWidget != null)
  253. {
  254. mEditWidget.Resize(0, 0, Math.Max(mWidth - GS!(24), 0), mHeight);
  255. }
  256. }
  257. public virtual bool WantsKeyHandling()
  258. {
  259. return true;
  260. }
  261. void EditKeyDownHandler(KeyDownEvent evt)
  262. {
  263. if (!WantsKeyHandling())
  264. return;
  265. if ((evt.mKeyCode == .Up) || (evt.mKeyCode == .Down) ||
  266. (evt.mKeyCode == .PageUp) || (evt.mKeyCode == .PageDown) ||
  267. (evt.mKeyCode == .Home) || (evt.mKeyCode == .End))
  268. {
  269. if (mCurMenuWidget != null)
  270. mCurMenuWidget.KeyDown(evt.mKeyCode, false);
  271. }
  272. if ((evt.mKeyCode == .Down) && (mCurMenuWidget == null))
  273. {
  274. ShowDropdown();
  275. var label = Label;
  276. for (let itemWidget in mCurMenuWidget.mItemWidgets)
  277. {
  278. if (itemWidget.mMenuItem.mLabel == label)
  279. mCurMenuWidget.SetSelection(@itemWidget.Index);
  280. }
  281. }
  282. if ((evt.mKeyCode == .Escape) && (mCurMenuWidget != null) && (mEditWidget != null))
  283. {
  284. mCurMenuWidget.Close();
  285. mEditWidget.SetFocus();
  286. evt.mHandled = true;
  287. }
  288. if ((evt.mKeyCode == .Return) && (mCurMenuWidget != null))
  289. {
  290. mCurMenuWidget.SubmitSelection();
  291. evt.mHandled = true;
  292. }
  293. }
  294. public override void KeyDown(KeyCode keyCode, bool isRepeat)
  295. {
  296. if (mCurMenuWidget != null)
  297. mCurMenuWidget.KeyDown(keyCode, isRepeat);
  298. }
  299. public void MakeEditable(DarkEditWidget editWidget = null)
  300. {
  301. if (mEditWidget == null)
  302. {
  303. mEditWidget = editWidget;
  304. if (mEditWidget == null)
  305. mEditWidget = new DarkEditWidget();
  306. mEditWidget.mDrawBox = false;
  307. mEditWidget.mOnSubmit.Add(new => EditSubmit);
  308. mEditWidget.mOnKeyDown.Add(new => EditKeyDownHandler);
  309. var ewc = (DarkEditWidgetContent)mEditWidget.mEditWidgetContent;
  310. ewc.mScrollToStartOnLostFocus = true;
  311. AddWidget(mEditWidget);
  312. ResizeComponents();
  313. }
  314. }
  315. private void EditSubmit(EditEvent theEvent)
  316. {
  317. if (mCurMenuWidget != null)
  318. {
  319. if (mCurMenuWidget.mSelectIdx != -1)
  320. {
  321. mCurMenuWidget.SubmitSelection();
  322. if (mCurMenuWidget != null)
  323. mCurMenuWidget.Close();
  324. }
  325. }
  326. }
  327. public override void KeyDown(KeyDownEvent keyEvent)
  328. {
  329. base.KeyDown(keyEvent);
  330. EditKeyDownHandler(keyEvent);
  331. }
  332. }
  333. }