GUISkinInspector.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. using System;
  4. using System.Collections.Generic;
  5. using BansheeEngine;
  6. namespace BansheeEditor
  7. {
  8. /** @addtogroup Inspectors
  9. * @{
  10. */
  11. /// <summary>
  12. /// Renders an inspector for the <see cref="GUISkin"/> resource.
  13. /// </summary>
  14. [CustomInspector(typeof(GUISkin))]
  15. internal class GUISkinInspector : Inspector
  16. {
  17. private GUIDictionaryField<string, GUIElementStyle, GUIElementStyleEntry> valuesField;
  18. private Dictionary<string, GUIElementStyle> styles = new Dictionary<string, GUIElementStyle>();
  19. /// <inheritdoc/>
  20. protected internal override void Initialize()
  21. {
  22. LoadResource();
  23. BuildGUI();
  24. }
  25. /// <inheritdoc/>
  26. protected internal override InspectableState Refresh()
  27. {
  28. valuesField.Refresh();
  29. return InspectableState.NotModified;
  30. }
  31. /// <summary>
  32. /// Recreates all the GUI elements used by this inspector.
  33. /// </summary>
  34. private void BuildGUI()
  35. {
  36. Layout.Clear();
  37. styles.Clear();
  38. GUISkin guiSkin = InspectedObject as GUISkin;
  39. if (guiSkin == null)
  40. return;
  41. string[] styleNames = guiSkin.StyleNames;
  42. foreach (var styleName in styleNames)
  43. styles[styleName] = guiSkin.GetStyle(styleName);
  44. valuesField = GUIDictionaryField<string, GUIElementStyle, GUIElementStyleEntry>.Create
  45. (new LocEdString("Styles"), styles, Layout);
  46. valuesField.IsExpanded = Persistent.GetBool("valuesField_Expanded");
  47. valuesField.OnExpand += x => Persistent.SetBool("valuesField_Expanded", x);
  48. valuesField.OnChanged += x =>
  49. {
  50. if (x != null)
  51. {
  52. foreach (var KVP in x)
  53. {
  54. if (guiSkin.HasStyle(KVP.Key))
  55. {
  56. GUIElementStyle oldValue = guiSkin.GetStyle(KVP.Key);
  57. if (oldValue != KVP.Value)
  58. guiSkin.SetStyle(KVP.Key, KVP.Value);
  59. }
  60. else
  61. guiSkin.SetStyle(KVP.Key, KVP.Value);
  62. }
  63. string[] oldStyleNames = guiSkin.StyleNames;
  64. foreach (var styleName in oldStyleNames)
  65. {
  66. if (!x.ContainsKey(styleName))
  67. guiSkin.RemoveStyle(styleName);
  68. }
  69. styles = x;
  70. }
  71. else
  72. {
  73. foreach (var KVP in styles)
  74. guiSkin.RemoveStyle(KVP.Key);
  75. styles.Clear();
  76. }
  77. EditorApplication.SetDirty(guiSkin);
  78. };
  79. valuesField.OnValueChanged += x =>
  80. {
  81. guiSkin.SetStyle(x, styles[x]);
  82. EditorApplication.SetDirty(guiSkin);
  83. };
  84. valuesField.OnValueRemoved += x =>
  85. {
  86. guiSkin.RemoveStyle(x);
  87. EditorApplication.SetDirty(guiSkin);
  88. };
  89. Layout.AddSpace(10);
  90. }
  91. /// <summary>
  92. /// Row element used for displaying GUI for GUI element style dictionary elements.
  93. /// </summary>
  94. private class GUIElementStyleEntry : GUIDictionaryFieldRow
  95. {
  96. private GUITextField keyField;
  97. private GUIElementStyleGUI valueField;
  98. /// <inheritdoc/>
  99. protected override GUILayoutX CreateKeyGUI(GUILayoutY layout)
  100. {
  101. GUILayoutX titleLayout = layout.AddLayoutX();
  102. keyField = new GUITextField(new LocEdString("Name"));
  103. titleLayout.AddElement(keyField);
  104. keyField.OnChanged += SetKey;
  105. return titleLayout;
  106. }
  107. /// <inheritdoc/>
  108. protected override void CreateValueGUI(GUILayoutY layout)
  109. {
  110. if(valueField == null)
  111. valueField = new GUIElementStyleGUI();
  112. valueField.BuildGUI(layout, Depth);
  113. }
  114. /// <inheritdoc/>
  115. protected override void OnEditModeChanged(bool editMode)
  116. {
  117. keyField.Disabled = !editMode;
  118. }
  119. /// <inheritdoc/>
  120. internal protected override InspectableState Refresh()
  121. {
  122. keyField.Value = GetKey<string>();
  123. return valueField.Refresh(GetValue<GUIElementStyle>());
  124. }
  125. }
  126. /// <summary>
  127. /// Creates GUI elements for editing/displaying <see cref="GUIElementStyle"/>
  128. /// </summary>
  129. private class GUIElementStyleGUI
  130. {
  131. private const int IndentAmount = 5;
  132. private GUIResourceField fontField;
  133. private GUIIntField fontSizeField;
  134. private GUIEnumField horzAlignField;
  135. private GUIEnumField vertAlignField;
  136. private GUIEnumField imagePositionField;
  137. private GUIToggleField wordWrapField;
  138. private GUIElementStateStyleGUI normalGUI;
  139. private GUIElementStateStyleGUI hoverGUI;
  140. private GUIElementStateStyleGUI activeGUI;
  141. private GUIElementStateStyleGUI focusedGUI;
  142. private GUIElementStateStyleGUI normalOnGUI;
  143. private GUIElementStateStyleGUI hoverOnGUI;
  144. private GUIElementStateStyleGUI activeOnGUI;
  145. private GUIElementStateStyleGUI focusedOnGUI;
  146. private RectOffsetGUI borderGUI;
  147. private RectOffsetGUI marginsGUI;
  148. private RectOffsetGUI contentOffsetGUI;
  149. private GUIToggleField fixedWidthField;
  150. private GUIIntField widthField;
  151. private GUIIntField minWidthField;
  152. private GUIIntField maxWidthField;
  153. private GUIToggleField fixedHeightField;
  154. private GUIIntField heightField;
  155. private GUIIntField minHeightField;
  156. private GUIIntField maxHeightField;
  157. private GUIElementStyle style;
  158. private bool isExpanded;
  159. private InspectableState modifiedState;
  160. /// <summary>
  161. /// Creates a new GUI element style GUI.
  162. /// </summary>
  163. public GUIElementStyleGUI()
  164. {
  165. normalGUI = new GUIElementStateStyleGUI();
  166. hoverGUI = new GUIElementStateStyleGUI();
  167. activeGUI = new GUIElementStateStyleGUI();
  168. focusedGUI = new GUIElementStateStyleGUI();
  169. normalOnGUI = new GUIElementStateStyleGUI();
  170. hoverOnGUI = new GUIElementStateStyleGUI();
  171. activeOnGUI = new GUIElementStateStyleGUI();
  172. focusedOnGUI = new GUIElementStateStyleGUI();
  173. }
  174. /// <summary>
  175. /// Builds GUI for the specified GUI element style.
  176. /// </summary>
  177. /// <param name="layout">Layout to append the GUI elements to.</param>
  178. /// <param name="depth">Determines the depth at which the element is rendered.</param>
  179. public void BuildGUI(GUILayout layout, int depth)
  180. {
  181. short backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
  182. string bgPanelStyle = depth % 2 == 0
  183. ? EditorStylesInternal.InspectorContentBgAlternate
  184. : EditorStylesInternal.InspectorContentBg;
  185. GUIToggle foldout = new GUIToggle(new LocEdString("Style"), EditorStyles.Foldout);
  186. foldout.AcceptsKeyFocus = false;
  187. GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
  188. layout.AddElement(foldout);
  189. GUIPanel panel = layout.AddPanel();
  190. GUIPanel backgroundPanel = panel.AddPanel(backgroundDepth);
  191. backgroundPanel.AddElement(inspectorContentBg);
  192. GUILayoutX guiIndentLayoutX = panel.AddLayoutX();
  193. guiIndentLayoutX.AddSpace(IndentAmount);
  194. GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
  195. guiIndentLayoutY.AddSpace(IndentAmount);
  196. GUILayoutY contentLayout = guiIndentLayoutY.AddLayoutY();
  197. guiIndentLayoutY.AddSpace(IndentAmount);
  198. guiIndentLayoutX.AddSpace(IndentAmount);
  199. fontField = new GUIResourceField(typeof (Font), new LocEdString("Font"));
  200. fontSizeField = new GUIIntField(new LocEdString("Font size"));
  201. horzAlignField = new GUIEnumField(typeof (TextHorzAlign), new LocEdString("Horizontal alignment"));
  202. vertAlignField = new GUIEnumField(typeof(TextVertAlign), new LocEdString("Vertical alignment"));
  203. imagePositionField = new GUIEnumField(typeof(GUIImagePosition), new LocEdString("Image position"));
  204. wordWrapField = new GUIToggleField(new LocEdString("Word wrap"));
  205. contentLayout.AddElement(fontField);
  206. contentLayout.AddElement(fontSizeField);
  207. contentLayout.AddElement(horzAlignField);
  208. contentLayout.AddElement(vertAlignField);
  209. contentLayout.AddElement(imagePositionField);
  210. contentLayout.AddElement(wordWrapField);
  211. normalGUI.BuildGUI(new LocEdString("Normal"), contentLayout);
  212. hoverGUI.BuildGUI(new LocEdString("Hover"), contentLayout);
  213. activeGUI.BuildGUI(new LocEdString("Active"), contentLayout);
  214. focusedGUI.BuildGUI(new LocEdString("Focused"), contentLayout);
  215. normalOnGUI.BuildGUI(new LocEdString("NormalOn"), contentLayout);
  216. hoverOnGUI.BuildGUI(new LocEdString("HoverOn"), contentLayout);
  217. activeOnGUI.BuildGUI(new LocEdString("ActiveOn"), contentLayout);
  218. focusedOnGUI.BuildGUI(new LocEdString("FocusedOn"), contentLayout);
  219. borderGUI = new RectOffsetGUI(new LocEdString("Border"), contentLayout);
  220. marginsGUI = new RectOffsetGUI(new LocEdString("Margins"), contentLayout);
  221. contentOffsetGUI = new RectOffsetGUI(new LocEdString("Content offset"), contentLayout);
  222. fixedWidthField = new GUIToggleField(new LocEdString("Fixed width"));
  223. widthField = new GUIIntField(new LocEdString("Width"));
  224. minWidthField = new GUIIntField(new LocEdString("Min. width"));
  225. maxWidthField = new GUIIntField(new LocEdString("Max. width"));
  226. fixedHeightField = new GUIToggleField(new LocEdString("Fixed height"));
  227. heightField = new GUIIntField(new LocEdString("Height"));
  228. minHeightField = new GUIIntField(new LocEdString("Min. height"));
  229. maxHeightField = new GUIIntField(new LocEdString("Max. height"));
  230. contentLayout.AddElement(fixedWidthField);
  231. contentLayout.AddElement(widthField);
  232. contentLayout.AddElement(minWidthField);
  233. contentLayout.AddElement(maxWidthField);
  234. contentLayout.AddElement(fixedHeightField);
  235. contentLayout.AddElement(heightField);
  236. contentLayout.AddElement(minHeightField);
  237. contentLayout.AddElement(maxHeightField);
  238. foldout.OnToggled += x =>
  239. {
  240. panel.Active = x;
  241. isExpanded = x;
  242. };
  243. fontField.OnChanged += x =>
  244. {
  245. Font font = Resources.Load<Font>(x);
  246. GetStyle().Font = font;
  247. MarkAsModified();
  248. ConfirmModify();
  249. };
  250. fontSizeField.OnChanged += x => { GetStyle().FontSize = x; MarkAsModified(); };
  251. fontSizeField.OnFocusLost += ConfirmModify;
  252. fontSizeField.OnConfirmed += ConfirmModify;
  253. horzAlignField.OnSelectionChanged += x =>
  254. {
  255. GetStyle().TextHorzAlign = (TextHorzAlign)x;
  256. MarkAsModified();
  257. ConfirmModify();
  258. };
  259. vertAlignField.OnSelectionChanged += x =>
  260. {
  261. GetStyle().TextVertAlign = (TextVertAlign)x;
  262. MarkAsModified();
  263. ConfirmModify();
  264. };
  265. imagePositionField.OnSelectionChanged += x =>
  266. {
  267. GetStyle().ImagePosition = (GUIImagePosition)x;
  268. MarkAsModified();
  269. ConfirmModify();
  270. };
  271. wordWrapField.OnChanged += x => { GetStyle().WordWrap = x; MarkAsModified(); ConfirmModify(); };
  272. normalGUI.OnChanged += x => { GetStyle().Normal = x; MarkAsModified(); ConfirmModify(); };
  273. hoverGUI.OnChanged += x => { GetStyle().Hover = x; MarkAsModified(); ConfirmModify(); };
  274. activeGUI.OnChanged += x => { GetStyle().Active = x; MarkAsModified(); ConfirmModify(); };
  275. focusedGUI.OnChanged += x => { GetStyle().Focused = x; MarkAsModified(); ConfirmModify(); };
  276. normalOnGUI.OnChanged += x => { GetStyle().NormalOn = x; MarkAsModified(); ConfirmModify(); };
  277. hoverOnGUI.OnChanged += x => { GetStyle().HoverOn = x; MarkAsModified(); ConfirmModify(); };
  278. activeOnGUI.OnChanged += x => { GetStyle().ActiveOn = x; MarkAsModified(); ConfirmModify(); };
  279. focusedOnGUI.OnChanged += x => { GetStyle().FocusedOn = x; MarkAsModified(); ConfirmModify(); };
  280. borderGUI.OnChanged += x => { GetStyle().Border = x; MarkAsModified(); };
  281. marginsGUI.OnChanged += x => { GetStyle().Margins = x; MarkAsModified(); };
  282. contentOffsetGUI.OnChanged += x => { GetStyle().ContentOffset = x; MarkAsModified(); };
  283. borderGUI.OnConfirmed += ConfirmModify;
  284. marginsGUI.OnConfirmed += ConfirmModify;
  285. contentOffsetGUI.OnConfirmed += ConfirmModify;
  286. fixedWidthField.OnChanged += x => { GetStyle().FixedWidth = x; MarkAsModified(); ConfirmModify(); };
  287. widthField.OnChanged += x => GetStyle().Width = x;
  288. widthField.OnFocusLost += ConfirmModify;
  289. widthField.OnConfirmed += ConfirmModify;
  290. minWidthField.OnChanged += x => GetStyle().MinWidth = x;
  291. minWidthField.OnFocusLost += ConfirmModify;
  292. minWidthField.OnConfirmed += ConfirmModify;
  293. maxWidthField.OnChanged += x => GetStyle().MaxWidth = x;
  294. maxWidthField.OnFocusLost += ConfirmModify;
  295. maxWidthField.OnConfirmed += ConfirmModify;
  296. fixedHeightField.OnChanged += x => { GetStyle().FixedHeight = x; MarkAsModified(); ConfirmModify(); };
  297. heightField.OnChanged += x => GetStyle().Height = x;
  298. heightField.OnFocusLost += ConfirmModify;
  299. heightField.OnConfirmed += ConfirmModify;
  300. minHeightField.OnChanged += x => GetStyle().MinHeight = x;
  301. minHeightField.OnFocusLost += ConfirmModify;
  302. minHeightField.OnConfirmed += ConfirmModify;
  303. maxHeightField.OnChanged += x => GetStyle().MaxHeight = x;
  304. maxHeightField.OnFocusLost += ConfirmModify;
  305. maxHeightField.OnConfirmed += ConfirmModify;
  306. foldout.Value = isExpanded;
  307. panel.Active = isExpanded;
  308. }
  309. /// <summary>
  310. /// Updates all GUI elements from the style if style changes.
  311. /// </summary>
  312. /// <param name="style">Style to display in the GUI.</param>
  313. /// <returns>State representing was anything modified between two last calls to <see cref="Refresh"/>.</returns>
  314. public InspectableState Refresh(GUIElementStyle style)
  315. {
  316. this.style = style;
  317. InspectableState oldModifiedState = modifiedState;
  318. if (modifiedState.HasFlag(InspectableState.Modified))
  319. modifiedState = InspectableState.NotModified;
  320. if (style == null)
  321. return oldModifiedState;
  322. fontField.Value = style.Font;
  323. fontSizeField.Value = style.FontSize;
  324. horzAlignField.Value = (ulong)style.TextHorzAlign;
  325. vertAlignField.Value = (ulong)style.TextVertAlign;
  326. imagePositionField.Value = (ulong)style.ImagePosition;
  327. wordWrapField.Value = style.WordWrap;
  328. normalGUI.Refresh(style.Normal);
  329. hoverGUI.Refresh(style.Hover);
  330. activeGUI.Refresh(style.Active);
  331. focusedGUI.Refresh(style.Focused);
  332. normalOnGUI.Refresh(style.NormalOn);
  333. hoverOnGUI.Refresh(style.HoverOn);
  334. activeOnGUI.Refresh(style.ActiveOn);
  335. focusedOnGUI.Refresh(style.FocusedOn);
  336. borderGUI.Refresh(style.Border);
  337. marginsGUI.Refresh(style.Margins);
  338. contentOffsetGUI.Refresh(style.ContentOffset);
  339. fixedWidthField.Value = style.FixedWidth;
  340. widthField.Value = style.Width;
  341. minWidthField.Value = style.MinWidth;
  342. maxWidthField.Value = style.MaxWidth;
  343. fixedHeightField.Value = style.FixedHeight;
  344. heightField.Value = style.Height;
  345. minHeightField.Value = style.MinHeight;
  346. maxHeightField.Value = style.MaxHeight;
  347. widthField.Active = style.FixedWidth;
  348. minWidthField.Active = !style.FixedWidth;
  349. maxWidthField.Active = !style.FixedWidth;
  350. heightField.Active = style.FixedHeight;
  351. minHeightField.Active = !style.FixedHeight;
  352. maxHeightField.Active = !style.FixedHeight;
  353. return oldModifiedState;
  354. }
  355. /// <summary>
  356. /// Returns the style displayed in the GUI.
  357. /// </summary>
  358. /// <returns>Style displayed in the GUI.</returns>
  359. private GUIElementStyle GetStyle()
  360. {
  361. return style;
  362. }
  363. /// <summary>
  364. /// Marks the contents of the style as modified.
  365. /// </summary>
  366. private void MarkAsModified()
  367. {
  368. modifiedState |= InspectableState.ModifyInProgress;
  369. }
  370. /// <summary>
  371. /// Confirms any queued modifications, signaling parent element.
  372. /// </summary>
  373. private void ConfirmModify()
  374. {
  375. if (modifiedState.HasFlag(InspectableState.ModifyInProgress))
  376. modifiedState |= InspectableState.Modified;
  377. }
  378. /// <summary>
  379. /// Creates GUI elements for editing/displaying <see cref="GUIElementStateStyle"/>
  380. /// </summary>
  381. private class GUIElementStateStyleGUI
  382. {
  383. private GUIElementStateStyle state;
  384. private GUIToggle foldout;
  385. private GUIResourceField textureField;
  386. private GUIColorField textColorField;
  387. private bool isExpanded;
  388. /// <summary>
  389. /// Triggered when some value in the style state changes.
  390. /// </summary>
  391. public Action<GUIElementStateStyle> OnChanged;
  392. /// <summary>
  393. /// Creates a new GUI element state style GUI.
  394. /// </summary>
  395. public GUIElementStateStyleGUI()
  396. { }
  397. /// <summary>
  398. /// Builds the GUI for the specified state style.
  399. /// </summary>
  400. /// <param name="title">Text to display on the title bar.</param>
  401. /// <param name="layout">Layout to append the GUI elements to.</param>
  402. public void BuildGUI(LocString title, GUILayout layout)
  403. {
  404. foldout = new GUIToggle(title, EditorStyles.Foldout);
  405. textureField = new GUIResourceField(typeof(SpriteTexture), new LocEdString("Texture"));
  406. textColorField = new GUIColorField(new LocEdString("Text color"));
  407. foldout.AcceptsKeyFocus = false;
  408. foldout.OnToggled += x =>
  409. {
  410. textureField.Active = x;
  411. textColorField.Active = x;
  412. isExpanded = x;
  413. };
  414. textureField.OnChanged += x =>
  415. {
  416. SpriteTexture texture = Resources.Load<SpriteTexture>(x);
  417. state.Texture = texture;
  418. if (OnChanged != null)
  419. OnChanged(state);
  420. };
  421. textColorField.OnChanged += x =>
  422. {
  423. state.TextColor = x;
  424. if (OnChanged != null)
  425. OnChanged(state);
  426. };
  427. layout.AddElement(foldout);
  428. layout.AddElement(textureField);
  429. layout.AddElement(textColorField);
  430. foldout.Value = isExpanded;
  431. textureField.Active = isExpanded;
  432. textColorField.Active = isExpanded;
  433. }
  434. /// <summary>
  435. /// Updates all GUI elements from the current state values.
  436. /// </summary>
  437. /// <param name="state">State object to display in the GUI.</param>
  438. public void Refresh(GUIElementStateStyle state)
  439. {
  440. this.state = state;
  441. textureField.Value = state.Texture;
  442. textColorField.Value = state.TextColor;
  443. }
  444. }
  445. /// <summary>
  446. /// Creates GUI elements for editing/displaying <see cref="RectOffset"/>
  447. /// </summary>
  448. private class RectOffsetGUI
  449. {
  450. private RectOffset offset;
  451. private GUIIntField offsetLeftField;
  452. private GUIIntField offsetRightField;
  453. private GUIIntField offsetTopField;
  454. private GUIIntField offsetBottomField;
  455. /// <summary>
  456. /// Triggered when some value in the offset rectangle changes.
  457. /// </summary>
  458. public Action<RectOffset> OnChanged;
  459. /// <summary>
  460. /// Triggered when the user confirms input.
  461. /// </summary>
  462. public Action OnConfirmed;
  463. /// <summary>
  464. /// Creates a new rectangle offset GUI.
  465. /// </summary>
  466. /// <param name="title">Text to display on the title bar.</param>
  467. /// <param name="layout">Layout to append the GUI elements to.</param>
  468. public RectOffsetGUI(LocString title, GUILayout layout)
  469. {
  470. GUILayoutX rectLayout = layout.AddLayoutX();
  471. rectLayout.AddElement(new GUILabel(title, GUIOption.FixedWidth(100)));
  472. GUILayoutY rectContentLayout = rectLayout.AddLayoutY();
  473. GUILayoutX rectTopRow = rectContentLayout.AddLayoutX();
  474. GUILayoutX rectBotRow = rectContentLayout.AddLayoutX();
  475. offsetLeftField = new GUIIntField(new LocEdString("Left"), 40);
  476. offsetRightField = new GUIIntField(new LocEdString("Right"), 40);
  477. offsetTopField = new GUIIntField(new LocEdString("Top"), 40);
  478. offsetBottomField = new GUIIntField(new LocEdString("Bottom"), 40);
  479. rectTopRow.AddElement(offsetLeftField);
  480. rectTopRow.AddElement(offsetRightField);
  481. rectBotRow.AddElement(offsetTopField);
  482. rectBotRow.AddElement(offsetBottomField);
  483. offsetLeftField.OnChanged += x =>
  484. {
  485. offset.left = x;
  486. if(OnChanged != null)
  487. OnChanged(offset);
  488. };
  489. offsetRightField.OnChanged += x =>
  490. {
  491. offset.right = x;
  492. if (OnChanged != null)
  493. OnChanged(offset);
  494. };
  495. offsetTopField.OnChanged += x =>
  496. {
  497. offset.top = x;
  498. if (OnChanged != null)
  499. OnChanged(offset);
  500. };
  501. offsetBottomField.OnChanged += x =>
  502. {
  503. offset.bottom = x;
  504. if (OnChanged != null)
  505. OnChanged(offset);
  506. };
  507. Action DoOnConfirmed = () =>
  508. {
  509. if (OnConfirmed != null)
  510. OnConfirmed();
  511. };
  512. offsetLeftField.OnConfirmed += DoOnConfirmed;
  513. offsetLeftField.OnFocusLost += DoOnConfirmed;
  514. offsetRightField.OnConfirmed += DoOnConfirmed;
  515. offsetRightField.OnFocusLost += DoOnConfirmed;
  516. offsetTopField.OnConfirmed += DoOnConfirmed;
  517. offsetTopField.OnFocusLost += DoOnConfirmed;
  518. offsetBottomField.OnConfirmed += DoOnConfirmed;
  519. offsetBottomField.OnFocusLost += DoOnConfirmed;
  520. }
  521. /// <summary>
  522. /// Updates all GUI elements from the offset.
  523. /// </summary>
  524. /// <param name="offset">Offset to update the GUI to.</param>
  525. public void Refresh(RectOffset offset)
  526. {
  527. this.offset = offset;
  528. offsetLeftField.Value = offset.left;
  529. offsetRightField.Value = offset.right;
  530. offsetTopField.Value = offset.top;
  531. offsetBottomField.Value = offset.bottom;
  532. }
  533. }
  534. }
  535. }
  536. /** @} */
  537. }