You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1288 lines
41KB

  1. //
  2. // based on NanoVG's example code by Mikko Mononen
  3. #include <stdio.h>
  4. #ifdef NANOVG_GLEW
  5. # include <GL/glew.h>
  6. #endif
  7. #ifdef __APPLE__
  8. # define GLFW_INCLUDE_GLCOREARB
  9. #endif
  10. #include <GLFW/glfw3.h>
  11. #include "nanovg.h"
  12. #define NANOVG_GL3_IMPLEMENTATION
  13. #include "nanovg_gl.h"
  14. #define BLENDISH_IMPLEMENTATION
  15. #include "blendish.h"
  16. #define OUI_IMPLEMENTATION
  17. #include "oui.h"
  18. ////////////////////////////////////////////////////////////////////////////////
  19. typedef enum {
  20. // label
  21. ST_LABEL = 0,
  22. // button
  23. ST_BUTTON = 1,
  24. // radio button
  25. ST_RADIO = 2,
  26. // progress slider
  27. ST_SLIDER = 3,
  28. // column
  29. ST_COLUMN = 4,
  30. // row
  31. ST_ROW = 5,
  32. // check button
  33. ST_CHECK = 6,
  34. // panel
  35. ST_PANEL = 7,
  36. // text
  37. ST_TEXT = 8,
  38. //
  39. ST_IGNORE = 9,
  40. ST_DEMOSTUFF = 10,
  41. // colored rectangle
  42. ST_RECT = 11,
  43. ST_HBOX = 12,
  44. ST_VBOX = 13,
  45. } SubType;
  46. typedef struct {
  47. int subtype;
  48. UIhandler handler;
  49. } UIData;
  50. typedef struct {
  51. UIData head;
  52. const char *label;
  53. NVGcolor color;
  54. } UIRectData;
  55. typedef struct {
  56. UIData head;
  57. int iconid;
  58. const char *label;
  59. } UIButtonData;
  60. typedef struct {
  61. UIData head;
  62. const char *label;
  63. int *option;
  64. } UICheckData;
  65. typedef struct {
  66. UIData head;
  67. int iconid;
  68. const char *label;
  69. int *value;
  70. } UIRadioData;
  71. typedef struct {
  72. UIData head;
  73. const char *label;
  74. float *progress;
  75. } UISliderData;
  76. typedef struct {
  77. UIData head;
  78. char *text;
  79. int maxsize;
  80. } UITextData;
  81. ////////////////////////////////////////////////////////////////////////////////
  82. void draw_demostuff(NVGcontext *vg, int x, int y, float w, float h);
  83. static struct NVGcontext* _vg = NULL;
  84. void ui_handler(int item, UIevent event) {
  85. UIData *data = (UIData *)uiGetHandle(item);
  86. if (data && data->handler) {
  87. data->handler(item, event);
  88. }
  89. }
  90. void init(NVGcontext *vg) {
  91. bndSetFont(nvgCreateFont(vg, "system", "../DejaVuSans.ttf"));
  92. bndSetIconImage(nvgCreateImage(vg, "../blender_icons16.png", 0));
  93. }
  94. void testrect(NVGcontext *vg, UIrect rect) {
  95. #if 0
  96. nvgBeginPath(vg);
  97. nvgRect(vg,rect.x+0.5,rect.y+0.5,rect.w-1,rect.h-1);
  98. nvgStrokeColor(vg,nvgRGBf(1,0,0));
  99. nvgStrokeWidth(vg,1);
  100. nvgStroke(vg);
  101. #endif
  102. }
  103. void drawUI(NVGcontext *vg, int item, int corners);
  104. void drawUIItems(NVGcontext *vg, int item, int corners) {
  105. int kid = uiFirstChild(item);
  106. while (kid > 0) {
  107. drawUI(vg, kid, corners);
  108. kid = uiNextSibling(kid);
  109. }
  110. }
  111. void drawUIItemsHbox(NVGcontext *vg, int item) {
  112. int kid = uiFirstChild(item);
  113. if (kid < 0) return;
  114. int nextkid = uiNextSibling(kid);
  115. if (nextkid < 0) {
  116. drawUI(vg, kid, BND_CORNER_NONE);
  117. } else {
  118. drawUI(vg, kid, BND_CORNER_RIGHT);
  119. kid = nextkid;
  120. while (uiNextSibling(kid) > 0) {
  121. drawUI(vg, kid, BND_CORNER_ALL);
  122. kid = uiNextSibling(kid);
  123. }
  124. drawUI(vg, kid, BND_CORNER_LEFT);
  125. }
  126. }
  127. void drawUIItemsVbox(NVGcontext *vg, int item) {
  128. int kid = uiFirstChild(item);
  129. if (kid < 0) return;
  130. int nextkid = uiNextSibling(kid);
  131. if (nextkid < 0) {
  132. drawUI(vg, kid, BND_CORNER_NONE);
  133. } else {
  134. drawUI(vg, kid, BND_CORNER_DOWN);
  135. kid = nextkid;
  136. while (uiNextSibling(kid) > 0) {
  137. drawUI(vg, kid, BND_CORNER_ALL);
  138. kid = uiNextSibling(kid);
  139. }
  140. drawUI(vg, kid, BND_CORNER_TOP);
  141. }
  142. }
  143. void drawUI(NVGcontext *vg, int item, int corners) {
  144. const UIData *head = (const UIData *)uiGetHandle(item);
  145. UIrect rect = uiGetRect(item);
  146. if (uiGetState(item) == UI_FROZEN) {
  147. nvgGlobalAlpha(vg, BND_DISABLED_ALPHA);
  148. }
  149. if (head) {
  150. switch(head->subtype) {
  151. default: {
  152. testrect(vg,rect);
  153. drawUIItems(vg,item,corners);
  154. } break;
  155. case ST_HBOX: {
  156. drawUIItemsHbox(vg, item);
  157. } break;
  158. case ST_VBOX: {
  159. drawUIItemsVbox(vg, item);
  160. } break;
  161. case ST_PANEL: {
  162. bndBevel(vg,rect.x,rect.y,rect.w,rect.h);
  163. drawUIItems(vg,item,corners);
  164. } break;
  165. case ST_LABEL: {
  166. assert(head);
  167. const UIButtonData *data = (UIButtonData*)head;
  168. bndLabel(vg,rect.x,rect.y,rect.w,rect.h,
  169. data->iconid,data->label);
  170. } break;
  171. case ST_BUTTON: {
  172. const UIButtonData *data = (UIButtonData*)head;
  173. bndToolButton(vg,rect.x,rect.y,rect.w,rect.h,
  174. corners,(BNDwidgetState)uiGetState(item),
  175. data->iconid,data->label);
  176. } break;
  177. case ST_CHECK: {
  178. const UICheckData *data = (UICheckData*)head;
  179. BNDwidgetState state = (BNDwidgetState)uiGetState(item);
  180. if (*data->option)
  181. state = BND_ACTIVE;
  182. bndOptionButton(vg,rect.x,rect.y,rect.w,rect.h, state,
  183. data->label);
  184. } break;
  185. case ST_RADIO:{
  186. const UIRadioData *data = (UIRadioData*)head;
  187. BNDwidgetState state = (BNDwidgetState)uiGetState(item);
  188. if (*data->value == item)
  189. state = BND_ACTIVE;
  190. bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h,
  191. corners,state,
  192. data->iconid,data->label);
  193. } break;
  194. case ST_SLIDER:{
  195. const UISliderData *data = (UISliderData*)head;
  196. BNDwidgetState state = (BNDwidgetState)uiGetState(item);
  197. static char value[32];
  198. sprintf(value,"%.0f%%",(*data->progress)*100.0f);
  199. bndSlider(vg,rect.x,rect.y,rect.w,rect.h,
  200. corners,state,
  201. *data->progress,data->label,value);
  202. } break;
  203. case ST_TEXT: {
  204. const UITextData *data = (UITextData*)head;
  205. BNDwidgetState state = (BNDwidgetState)uiGetState(item);
  206. int idx = strlen(data->text);
  207. bndTextField(vg,rect.x,rect.y,rect.w,rect.h,
  208. corners,state, -1, data->text, idx, idx);
  209. } break;
  210. case ST_DEMOSTUFF: {
  211. draw_demostuff(vg, rect.x, rect.y, rect.w, rect.h);
  212. } break;
  213. case ST_RECT: {
  214. const UIRectData *data = (UIRectData*)head;
  215. if (rect.w && rect.h) {
  216. BNDwidgetState state = (BNDwidgetState)uiGetState(item);
  217. nvgSave(vg);
  218. nvgStrokeColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.9f));
  219. if (state != BND_DEFAULT) {
  220. nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.5f));
  221. } else {
  222. nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.1f));
  223. }
  224. nvgStrokeWidth(vg,2);
  225. nvgBeginPath(vg);
  226. #if 0
  227. nvgRect(vg,rect.x,rect.y,rect.w,rect.h);
  228. #else
  229. nvgRoundedRect(vg,rect.x,rect.y,rect.w,rect.h,3);
  230. #endif
  231. nvgFill(vg);
  232. nvgStroke(vg);
  233. if (state != BND_DEFAULT) {
  234. nvgFillColor(vg, nvgRGBAf(0.0f,0.0f,0.0f,1.0f));
  235. nvgFontSize(vg, 15.0f);
  236. nvgBeginPath(vg);
  237. nvgTextAlign(vg, NVG_ALIGN_TOP|NVG_ALIGN_CENTER);
  238. nvgTextBox(vg, rect.x, rect.y+rect.h*0.3f, rect.w, data->label, NULL);
  239. }
  240. nvgRestore(vg);
  241. }
  242. nvgSave(vg);
  243. nvgIntersectScissor(vg, rect.x, rect.y, rect.w, rect.h);
  244. drawUIItems(vg,item,corners);
  245. nvgRestore(vg);
  246. } break;
  247. }
  248. } else {
  249. testrect(vg,rect);
  250. drawUIItems(vg,item,corners);
  251. }
  252. if (uiGetState(item) == UI_FROZEN) {
  253. nvgGlobalAlpha(vg, 1.0);
  254. }
  255. }
  256. int colorrect(const char *label, NVGcolor color) {
  257. int item = uiItem();
  258. UIRectData *data = (UIRectData *)uiAllocHandle(item, sizeof(UIRectData));
  259. data->head.subtype = ST_RECT;
  260. data->head.handler = NULL;
  261. data->label = label;
  262. data->color = color;
  263. uiSetEvents(item, UI_BUTTON0_DOWN);
  264. return item;
  265. }
  266. int label(int iconid, const char *label) {
  267. int item = uiItem();
  268. uiSetSize(item, 0, BND_WIDGET_HEIGHT);
  269. UIButtonData *data = (UIButtonData *)uiAllocHandle(item, sizeof(UIButtonData));
  270. data->head.subtype = ST_LABEL;
  271. data->head.handler = NULL;
  272. data->iconid = iconid;
  273. data->label = label;
  274. return item;
  275. }
  276. void demohandler(int item, UIevent event) {
  277. const UIButtonData *data = (const UIButtonData *)uiGetHandle(item);
  278. printf("clicked: %p %s\n", uiGetHandle(item), data->label);
  279. }
  280. int button(int iconid, const char *label, UIhandler handler) {
  281. // create new ui item
  282. int item = uiItem();
  283. // set size of wiget; horizontal size is dynamic, vertical is fixed
  284. uiSetSize(item, 0, BND_WIDGET_HEIGHT);
  285. uiSetEvents(item, UI_BUTTON0_HOT_UP);
  286. // store some custom data with the button that we use for styling
  287. UIButtonData *data = (UIButtonData *)uiAllocHandle(item, sizeof(UIButtonData));
  288. data->head.subtype = ST_BUTTON;
  289. data->head.handler = handler;
  290. data->iconid = iconid;
  291. data->label = label;
  292. return item;
  293. }
  294. void checkhandler(int item, UIevent event) {
  295. const UICheckData *data = (const UICheckData *)uiGetHandle(item);
  296. *data->option = !(*data->option);
  297. }
  298. int check(const char *label, int *option) {
  299. // create new ui item
  300. int item = uiItem();
  301. // set size of wiget; horizontal size is dynamic, vertical is fixed
  302. uiSetSize(item, 0, BND_WIDGET_HEIGHT);
  303. // attach event handler e.g. demohandler above
  304. uiSetEvents(item, UI_BUTTON0_DOWN);
  305. // store some custom data with the button that we use for styling
  306. UICheckData *data = (UICheckData *)uiAllocHandle(item, sizeof(UICheckData));
  307. data->head.subtype = ST_CHECK;
  308. data->head.handler = checkhandler;
  309. data->label = label;
  310. data->option = option;
  311. return item;
  312. }
  313. // simple logic for a slider
  314. // starting offset of the currently active slider
  315. static float sliderstart = 0.0;
  316. // event handler for slider (same handler for all sliders)
  317. void sliderhandler(int item, UIevent event) {
  318. // retrieve the custom data we saved with the slider
  319. UISliderData *data = (UISliderData *)uiGetHandle(item);
  320. switch(event) {
  321. default: break;
  322. case UI_BUTTON0_DOWN: {
  323. // button was pressed for the first time; capture initial
  324. // slider value.
  325. sliderstart = *data->progress;
  326. } break;
  327. case UI_BUTTON0_CAPTURE: {
  328. // called for every frame that the button is pressed.
  329. // get the delta between the click point and the current
  330. // mouse position
  331. UIvec2 pos = uiGetCursorStartDelta();
  332. // get the items layouted rectangle
  333. UIrect rc = uiGetRect(item);
  334. // calculate our new offset and clamp
  335. float value = sliderstart + ((float)pos.x / (float)rc.w);
  336. value = (value<0)?0:(value>1)?1:value;
  337. // assign the new value
  338. *data->progress = value;
  339. } break;
  340. }
  341. }
  342. int slider(const char *label, float *progress) {
  343. // create new ui item
  344. int item = uiItem();
  345. // set size of wiget; horizontal size is dynamic, vertical is fixed
  346. uiSetSize(item, 0, BND_WIDGET_HEIGHT);
  347. // attach our slider event handler and capture two classes of events
  348. uiSetEvents(item, UI_BUTTON0_DOWN | UI_BUTTON0_CAPTURE);
  349. // store some custom data with the button that we use for styling
  350. // and logic, e.g. the pointer to the data we want to alter.
  351. UISliderData *data = (UISliderData *)uiAllocHandle(item, sizeof(UISliderData));
  352. data->head.subtype = ST_SLIDER;
  353. data->head.handler = sliderhandler;
  354. data->label = label;
  355. data->progress = progress;
  356. return item;
  357. }
  358. void textboxhandler(int item, UIevent event) {
  359. UITextData *data = (UITextData *)uiGetHandle(item);
  360. switch(event) {
  361. default: break;
  362. case UI_BUTTON0_DOWN: {
  363. uiFocus(item);
  364. } break;
  365. case UI_KEY_DOWN: {
  366. unsigned int key = uiGetKey();
  367. switch(key) {
  368. default: break;
  369. case GLFW_KEY_BACKSPACE: {
  370. int size = strlen(data->text);
  371. if (!size) return;
  372. data->text[size-1] = 0;
  373. } break;
  374. case GLFW_KEY_ENTER: {
  375. uiFocus(-1);
  376. } break;
  377. }
  378. } break;
  379. case UI_CHAR: {
  380. unsigned int key = uiGetKey();
  381. if ((key > 255)||(key < 32)) return;
  382. int size = strlen(data->text);
  383. if (size >= (data->maxsize-1)) return;
  384. data->text[size] = (char)key;
  385. } break;
  386. }
  387. }
  388. int textbox(char *text, int maxsize) {
  389. int item = uiItem();
  390. uiSetSize(item, 0, BND_WIDGET_HEIGHT);
  391. uiSetEvents(item, UI_BUTTON0_DOWN | UI_KEY_DOWN | UI_CHAR);
  392. // store some custom data with the button that we use for styling
  393. // and logic, e.g. the pointer to the data we want to alter.
  394. UITextData *data = (UITextData *)uiAllocHandle(item, sizeof(UITextData));
  395. data->head.subtype = ST_TEXT;
  396. data->head.handler = textboxhandler;
  397. data->text = text;
  398. data->maxsize = maxsize;
  399. return item;
  400. }
  401. // simple logic for a radio button
  402. void radiohandler(int item, UIevent event) {
  403. UIRadioData *data = (UIRadioData *)uiGetHandle(item);
  404. *data->value = item;
  405. }
  406. int radio(int iconid, const char *label, int *value) {
  407. int item = uiItem();
  408. uiSetSize(item, label?0:BND_TOOL_WIDTH, BND_WIDGET_HEIGHT);
  409. UIRadioData *data = (UIRadioData *)uiAllocHandle(item, sizeof(UIRadioData));
  410. data->head.subtype = ST_RADIO;
  411. data->head.handler = radiohandler;
  412. data->iconid = iconid;
  413. data->label = label;
  414. data->value = value;
  415. uiSetEvents(item, UI_BUTTON0_DOWN);
  416. return item;
  417. }
  418. int panel() {
  419. int item = uiItem();
  420. UIData *data = (UIData *)uiAllocHandle(item, sizeof(UIData));
  421. data->subtype = ST_PANEL;
  422. data->handler = NULL;
  423. return item;
  424. }
  425. int hbox() {
  426. int item = uiItem();
  427. UIData *data = (UIData *)uiAllocHandle(item, sizeof(UIData));
  428. data->subtype = ST_HBOX;
  429. data->handler = NULL;
  430. uiSetBox(item, UI_ROW);
  431. return item;
  432. }
  433. int vbox() {
  434. int item = uiItem();
  435. UIData *data = (UIData *)uiAllocHandle(item, sizeof(UIData));
  436. data->subtype = ST_VBOX;
  437. data->handler = NULL;
  438. uiSetBox(item, UI_COLUMN);
  439. return item;
  440. }
  441. int column_append(int parent, int item) {
  442. uiInsert(parent, item);
  443. // fill parent horizontally, anchor to previous item vertically
  444. uiSetLayout(item, UI_HFILL);
  445. uiSetMargins(item, 0, 1, 0, 0);
  446. return item;
  447. }
  448. int column() {
  449. int item = uiItem();
  450. uiSetBox(item, UI_COLUMN);
  451. return item;
  452. }
  453. int vgroup_append(int parent, int item) {
  454. uiInsert(parent, item);
  455. // fill parent horizontally, anchor to previous item vertically
  456. uiSetLayout(item, UI_HFILL);
  457. return item;
  458. }
  459. int vgroup() {
  460. int item = uiItem();
  461. uiSetBox(item, UI_COLUMN);
  462. return item;
  463. }
  464. int hgroup_append(int parent, int item) {
  465. uiInsert(parent, item);
  466. uiSetLayout(item, UI_HFILL);
  467. return item;
  468. }
  469. int hgroup_append_fixed(int parent, int item) {
  470. uiInsert(parent, item);
  471. return item;
  472. }
  473. int hgroup() {
  474. int item = uiItem();
  475. uiSetBox(item, UI_ROW);
  476. return item;
  477. }
  478. int row_append(int parent, int item) {
  479. uiInsert(parent, item);
  480. uiSetLayout(item, UI_HFILL);
  481. return item;
  482. }
  483. int row() {
  484. int item = uiItem();
  485. uiSetBox(item, UI_ROW);
  486. return item;
  487. }
  488. void draw_noodles(NVGcontext *vg, int x, int y) {
  489. int w = 200;
  490. int s = 70;
  491. bndNodeBackground(vg, x+w, y-50, 100, 200, BND_DEFAULT, BND_ICONID(6,3),
  492. "Default", nvgRGBf(0.392f,0.392f,0.392f));
  493. bndNodeBackground(vg, x+w+120, y-50, 100, 200, BND_HOVER, BND_ICONID(6,3),
  494. "Hover", nvgRGBf(0.392f,0.392f,0.392f));
  495. bndNodeBackground(vg, x+w+240, y-50, 100, 200, BND_ACTIVE, BND_ICONID(6,3),
  496. "Active", nvgRGBf(0.392f,0.392f,0.392f));
  497. for (int i = 0; i < 9; ++i) {
  498. int a = i%3;
  499. int b = i/3;
  500. bndNodeWire(vg, x, y+s*a, x+w, y+s*b, (BNDwidgetState)a, (BNDwidgetState)b);
  501. }
  502. bndNodePort(vg, x, y, BND_DEFAULT, nvgRGBf(0.5f, 0.5f, 0.5f));
  503. bndNodePort(vg, x+w, y, BND_DEFAULT, nvgRGBf(0.5f, 0.5f, 0.5f));
  504. bndNodePort(vg, x, y+s, BND_HOVER, nvgRGBf(0.5f, 0.5f, 0.5f));
  505. bndNodePort(vg, x+w, y+s, BND_HOVER, nvgRGBf(0.5f, 0.5f, 0.5f));
  506. bndNodePort(vg, x, y+2*s, BND_ACTIVE, nvgRGBf(0.5f, 0.5f, 0.5f));
  507. bndNodePort(vg, x+w, y+2*s, BND_ACTIVE, nvgRGBf(0.5f, 0.5f, 0.5f));
  508. }
  509. static void roothandler(int parent, UIevent event) {
  510. switch(event) {
  511. default: break;
  512. case UI_SCROLL: {
  513. UIvec2 pos = uiGetScroll();
  514. printf("scroll! %d %d\n", pos.x, pos.y);
  515. } break;
  516. case UI_BUTTON0_DOWN: {
  517. printf("%d clicks\n", uiGetClicks());
  518. } break;
  519. }
  520. }
  521. void draw_demostuff(NVGcontext *vg, int x, int y, float w, float h) {
  522. nvgSave(vg);
  523. nvgTranslate(vg, x, y);
  524. bndSplitterWidgets(vg, 0, 0, w, h);
  525. x = 10;
  526. y = 10;
  527. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  528. BND_ICONID(6,3),"Default");
  529. y += 25;
  530. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  531. BND_ICONID(6,3),"Hovered");
  532. y += 25;
  533. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  534. BND_ICONID(6,3),"Active");
  535. y += 40;
  536. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  537. -1,"Default");
  538. y += 25;
  539. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  540. -1,"Hovered");
  541. y += 25;
  542. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  543. -1,"Active");
  544. y += 25;
  545. bndLabel(vg,x,y,120,BND_WIDGET_HEIGHT,-1,"Label:");
  546. y += BND_WIDGET_HEIGHT;
  547. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  548. -1, "Default");
  549. y += 25;
  550. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  551. -1, "Hovered");
  552. y += 25;
  553. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  554. -1, "Active");
  555. y += 25;
  556. int ry = y;
  557. int rx = x;
  558. y = 10;
  559. x += 130;
  560. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_DEFAULT,"Default");
  561. y += 25;
  562. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_HOVER,"Hovered");
  563. y += 25;
  564. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_ACTIVE,"Active");
  565. y += 40;
  566. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_DOWN,BND_DEFAULT,
  567. "Top","100");
  568. y += BND_WIDGET_HEIGHT-2;
  569. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  570. "Center","100");
  571. y += BND_WIDGET_HEIGHT-2;
  572. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_TOP,BND_DEFAULT,
  573. "Bottom","100");
  574. int mx = x-30;
  575. int my = y-12;
  576. int mw = 120;
  577. bndMenuBackground(vg,mx,my,mw,120,BND_CORNER_TOP);
  578. bndMenuLabel(vg,mx,my,mw,BND_WIDGET_HEIGHT,-1,"Menu Title");
  579. my += BND_WIDGET_HEIGHT-2;
  580. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_DEFAULT,
  581. BND_ICONID(17,3),"Default");
  582. my += BND_WIDGET_HEIGHT-2;
  583. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_HOVER,
  584. BND_ICONID(18,3),"Hovered");
  585. my += BND_WIDGET_HEIGHT-2;
  586. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_ACTIVE,
  587. BND_ICONID(19,3),"Active");
  588. y = 10;
  589. x += 130;
  590. int ox = x;
  591. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  592. "Default","100");
  593. y += 25;
  594. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  595. "Hovered","100");
  596. y += 25;
  597. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  598. "Active","100");
  599. y += 40;
  600. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,BND_DEFAULT,
  601. -1,"One");
  602. x += 60-1;
  603. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  604. -1,"Two");
  605. x += 60-1;
  606. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  607. -1,"Three");
  608. x += 60-1;
  609. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,BND_ACTIVE,
  610. -1,"Butts");
  611. x = ox;
  612. y += 40;
  613. float progress_value = fmodf(glfwGetTime()/10.0,1.0);
  614. char progress_label[32];
  615. sprintf(progress_label, "%d%%", int(progress_value*100+0.5f));
  616. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  617. progress_value,"Default",progress_label);
  618. y += 25;
  619. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  620. progress_value,"Hovered",progress_label);
  621. y += 25;
  622. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  623. progress_value,"Active",progress_label);
  624. int rw = x+240-rx;
  625. float s_offset = sinf(glfwGetTime()/2.0)*0.5+0.5;
  626. float s_size = cosf(glfwGetTime()/3.11)*0.5+0.5;
  627. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_DEFAULT,s_offset,s_size);
  628. ry += 20;
  629. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_HOVER,s_offset,s_size);
  630. ry += 20;
  631. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_ACTIVE,s_offset,s_size);
  632. const char edit_text[] = "The quick brown fox";
  633. int textlen = strlen(edit_text)+1;
  634. int t = int(glfwGetTime()*2);
  635. int idx1 = (t/textlen)%textlen;
  636. int idx2 = idx1 + (t%(textlen-idx1));
  637. ry += 25;
  638. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  639. -1, edit_text, idx1, idx2);
  640. ry += 25;
  641. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  642. -1, edit_text, idx1, idx2);
  643. ry += 25;
  644. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  645. -1, edit_text, idx1, idx2);
  646. draw_noodles(vg, 20, ry+50);
  647. rx += rw + 20;
  648. ry = 10;
  649. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_DEFAULT,s_offset,s_size);
  650. rx += 20;
  651. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_HOVER,s_offset,s_size);
  652. rx += 20;
  653. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_ACTIVE,s_offset,s_size);
  654. x = ox;
  655. y += 40;
  656. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,
  657. BND_DEFAULT,BND_ICONID(0,10),NULL);
  658. x += BND_TOOL_WIDTH-1;
  659. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  660. BND_DEFAULT,BND_ICONID(1,10),NULL);
  661. x += BND_TOOL_WIDTH-1;
  662. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  663. BND_DEFAULT,BND_ICONID(2,10),NULL);
  664. x += BND_TOOL_WIDTH-1;
  665. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  666. BND_DEFAULT,BND_ICONID(3,10),NULL);
  667. x += BND_TOOL_WIDTH-1;
  668. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  669. BND_DEFAULT,BND_ICONID(4,10),NULL);
  670. x += BND_TOOL_WIDTH-1;
  671. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,
  672. BND_DEFAULT,BND_ICONID(5,10),NULL);
  673. x += BND_TOOL_WIDTH-1;
  674. x += 5;
  675. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,
  676. BND_DEFAULT,BND_ICONID(0,11),NULL);
  677. x += BND_TOOL_WIDTH-1;
  678. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  679. BND_DEFAULT,BND_ICONID(1,11),NULL);
  680. x += BND_TOOL_WIDTH-1;
  681. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  682. BND_DEFAULT,BND_ICONID(2,11),NULL);
  683. x += BND_TOOL_WIDTH-1;
  684. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  685. BND_DEFAULT,BND_ICONID(3,11),NULL);
  686. x += BND_TOOL_WIDTH-1;
  687. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  688. BND_ACTIVE,BND_ICONID(4,11),NULL);
  689. x += BND_TOOL_WIDTH-1;
  690. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,
  691. BND_DEFAULT,BND_ICONID(5,11),NULL);
  692. nvgRestore(vg);
  693. }
  694. static int enum1 = -1;
  695. void build_democontent(int parent) {
  696. // some persistent variables for demonstration
  697. static float progress1 = 0.25f;
  698. static float progress2 = 0.75f;
  699. static int option1 = 1;
  700. static int option2 = 0;
  701. static int option3 = 0;
  702. int col = column();
  703. uiInsert(parent, col);
  704. uiSetMargins(col, 10, 10, 10, 10);
  705. uiSetLayout(col, UI_TOP|UI_HFILL);
  706. column_append(col, button(BND_ICON_GHOST, "Item 1", demohandler));
  707. if (option3)
  708. column_append(col, button(BND_ICON_GHOST, "Item 2", demohandler));
  709. {
  710. int h = column_append(col, hbox());
  711. hgroup_append(h, radio(BND_ICON_GHOST, "Item 3.0", &enum1));
  712. if (option2)
  713. uiSetMargins(hgroup_append_fixed(h, radio(BND_ICON_REC, NULL, &enum1)), -1,0,0,0);
  714. uiSetMargins(hgroup_append_fixed(h, radio(BND_ICON_PLAY, NULL, &enum1)), -1,0,0,0);
  715. uiSetMargins(hgroup_append(h, radio(BND_ICON_GHOST, "Item 3.3", &enum1)), -1,0,0,0);
  716. }
  717. {
  718. int rows = column_append(col, row());
  719. int coll = row_append(rows, vgroup());
  720. vgroup_append(coll, label(-1, "Items 4.0:"));
  721. coll = vgroup_append(coll, vbox());
  722. vgroup_append(coll, button(BND_ICON_GHOST, "Item 4.0.0", demohandler));
  723. uiSetMargins(vgroup_append(coll, button(BND_ICON_GHOST, "Item 4.0.1", demohandler)),0,-2,0,0);
  724. int colr = row_append(rows, vgroup());
  725. uiSetMargins(colr, 8, 0, 0, 0);
  726. uiSetFrozen(colr, option1);
  727. vgroup_append(colr, label(-1, "Items 4.1:"));
  728. colr = vgroup_append(colr, vbox());
  729. vgroup_append(colr, slider("Item 4.1.0", &progress1));
  730. uiSetMargins(vgroup_append(colr, slider("Item 4.1.1", &progress2)),0,-2,0,0);
  731. }
  732. column_append(col, button(BND_ICON_GHOST, "Item 5", NULL));
  733. static char textbuffer[1024] = "The quick brown fox.";
  734. column_append(col, textbox(textbuffer, 1024));
  735. column_append(col, check("Frozen", &option1));
  736. column_append(col, check("Item 7", &option2));
  737. column_append(col, check("Item 8", &option3));
  738. }
  739. int demorect(int parent, const char *label, float hue, int box, int layout, int w, int h, int m1, int m2, int m3, int m4) {
  740. int item = colorrect(label, nvgHSL(hue, 1.0f, 0.8f));
  741. uiSetLayout(item, layout);
  742. uiSetBox(item, box);
  743. uiSetMargins(item, m1, m2, m3, m4);
  744. uiSetSize(item, w, h);
  745. uiInsert(parent, item);
  746. return item;
  747. }
  748. void build_layoutdemo(int parent) {
  749. const int M = 10;
  750. const int S = 150;
  751. int box = demorect(parent, "Box( UI_LAYOUT )\nLayout( UI_FILL )", 0.6f, UI_LAYOUT, UI_FILL, 0, 0, M, M, M, M);
  752. demorect(box, "Layout( UI_HFILL | UI_TOP )", 0.7f, 0, UI_HFILL|UI_TOP, S, S+M, M, M, M, 0);
  753. demorect(box, "Layout( UI_HFILL )", 0.7f, 0, UI_HFILL, S, S+2*M, M, 0, M, 0);
  754. demorect(box, "Layout( UI_HFILL | UI_DOWN )", 0.7f, 0, UI_HFILL|UI_DOWN, S, S+M, M, 0, M, M);
  755. demorect(box, "Layout( UI_LEFT | UI_VFILL )", 0.7f, 0, UI_LEFT|UI_VFILL, S+M, S, M, M, 0, M);
  756. demorect(box, "Layout( UI_VFILL )", 0.7f, 0, UI_VFILL, S+2*M, S, 0, M, 0, M);
  757. demorect(box, "Layout( UI_RIGHT | UI_VFILL )", 0.7f, 0, UI_RIGHT|UI_VFILL, S+M, S, 0, M, M, M);
  758. demorect(box, "Layout( UI_LEFT | UI_TOP )", 0.55f, 0, UI_LEFT|UI_TOP, S, S, M, M, 0, 0);
  759. demorect(box, "Layout( UI_TOP )", 0.57f, 0, UI_TOP, S, S, 0, M, 0, 0);
  760. demorect(box, "Layout( UI_RIGHT | UI_TOP )", 0.55f, 0, UI_RIGHT|UI_TOP, S, S, 0, M, M, 0);
  761. demorect(box, "Layout( UI_LEFT )", 0.57f, 0, UI_LEFT, S, S, M, 0, 0, 0);
  762. demorect(box, "Layout( UI_CENTER )", 0.59f, 0, UI_CENTER, S, S, 0, 0, 0, 0);
  763. demorect(box, "Layout( UI_RIGHT )", 0.57f, 0, UI_RIGHT, S, S, 0, 0, M, 0);
  764. demorect(box, "Layout( UI_LEFT | UI_DOWN )", 0.55f, 0, UI_LEFT|UI_DOWN, S, S, M, 0, 0, M);
  765. demorect(box, "Layout( UI_DOWN)", 0.57f, 0, UI_DOWN, S, S, 0, 0, 0, M);
  766. demorect(box, "Layout( UI_RIGHT | UI_DOWN )", 0.55f, 0, UI_RIGHT|UI_DOWN, S, S, 0, 0, M, M);
  767. }
  768. void build_rowdemo(int parent) {
  769. uiSetBox(parent, UI_COLUMN);
  770. const int M = 10;
  771. const int S = 200;
  772. const int T = 100;
  773. {
  774. int box = demorect(parent, "Box( UI_ROW )\nLayout( UI_LEFT | UI_VFILL )", 0.6f, UI_ROW, UI_LEFT|UI_VFILL, 0, S, M, M, M, M);
  775. demorect(box, "Layout( UI_TOP )", 0.05f, 0, UI_TOP, T, T, M, M, M, 0);
  776. demorect(box, "Layout( UI_VCENTER )", 0.1f, 0, UI_VCENTER, T, T, 0, 0, M, 0);
  777. demorect(box, "Layout( UI_VFILL )", 0.15f, 0, UI_VFILL, T, T, 0, M, M, M);
  778. demorect(box, "Layout( UI_DOWN )", 0.25f, 0, UI_DOWN, T, T, 0, 0, M, M);
  779. }
  780. {
  781. int box = demorect(parent, "Box( UI_ROW | UI_JUSTIFY )\nLayout( UI_FILL )", 0.6f, UI_ROW|UI_JUSTIFY, UI_FILL, 0, S, M, 0, M, M);
  782. demorect(box, "Layout( UI_TOP )", 0.05f, 0, UI_TOP, T, T, M, M, M, 0);
  783. demorect(box, "Layout( UI_VCENTER )", 0.1f, 0, UI_VCENTER, T, T, 0, 0, M, 0);
  784. demorect(box, "Layout( UI_VFILL )", 0.15f, 0, UI_VFILL, T, T, 0, M, M, M);
  785. demorect(box, "Layout( UI_DOWN )", 0.25f, 0, UI_DOWN, T, T, 0, 0, M, M);
  786. }
  787. {
  788. int box = demorect(parent, "Box( UI_ROW )\nLayout( UI_FILL )", 0.6f, UI_ROW, UI_FILL, 0, S, M, 0, M, M);
  789. demorect(box, "Layout( UI_TOP )", 0.05f, 0, UI_TOP, T, T, M, M, M, 0);
  790. demorect(box, "Layout( UI_VCENTER )", 0.1f, 0, UI_VCENTER, T, T, 0, 0, M, 0);
  791. demorect(box, "Layout( UI_VFILL )", 0.15f, 0, UI_VFILL, T, T, 0, M, M, M);
  792. demorect(box, "Layout( UI_HFILL )", 0.2f, 0, UI_HFILL, T, T, 0, 0, M, 0);
  793. demorect(box, "Layout( UI_HFILL )", 0.2f, 0, UI_HFILL, T, T, 0, 0, M, 0);
  794. demorect(box, "Layout( UI_HFILL )", 0.2f, 0, UI_HFILL, T, T, 0, 0, M, 0);
  795. demorect(box, "Layout( UI_DOWN )", 0.25f, 0, UI_DOWN, T, T, 0, 0, M, M);
  796. }
  797. }
  798. void build_columndemo(int parent) {
  799. uiSetBox(parent, UI_ROW);
  800. const int M = 10;
  801. const int S = 200;
  802. const int T = 100;
  803. {
  804. int box = demorect(parent, "Box( UI_COLUMN )\nLayout( UI_TOP | UI_HFILL )", 0.6f, UI_COLUMN, UI_TOP|UI_HFILL, S, 0, M, M, M, M);
  805. demorect(box, "Layout( UI_LEFT )", 0.05f, 0, UI_LEFT, T, T, M, M, 0, M);
  806. demorect(box, "Layout( UI_HCENTER )", 0.1f, 0, UI_HCENTER, T, T, 0, 0, 0, M);
  807. demorect(box, "Layout( UI_HFILL )", 0.15f, 0, UI_HFILL, T, T, M, 0, M, M);
  808. demorect(box, "Layout( UI_RIGHT )", 0.25f, 0, UI_RIGHT, T, T, 0, 0, M, M);
  809. }
  810. {
  811. int box = demorect(parent, "Box( UI_COLUMN )\nLayout( UI_FILL )", 0.6f, UI_COLUMN, UI_FILL, S, 0, 0, M, M, M);
  812. demorect(box, "Layout( UI_LEFT )", 0.05f, 0, UI_LEFT, T, T, M, M, 0, M);
  813. demorect(box, "Layout( UI_HCENTER )", 0.1f, 0, UI_HCENTER, T, T, 0, 0, 0, M);
  814. demorect(box, "Layout( UI_HFILL )", 0.15f, 0, UI_HFILL, T, T, M, 0, M, M);
  815. demorect(box, "Layout( UI_RIGHT )", 0.25f, 0, UI_RIGHT, T, T, 0, 0, M, M);
  816. }
  817. {
  818. int box = demorect(parent, "Box( UI_COLUMN )\nLayout( UI_FILL )", 0.6f, UI_COLUMN, UI_FILL, S, 0, 0, M, M, M);
  819. demorect(box, "Layout( UI_LEFT )", 0.05f, 0, UI_LEFT, T, T, M, M, 0, M);
  820. demorect(box, "Layout( UI_HCENTER )", 0.1f, 0, UI_HCENTER, T, T, 0, 0, 0, M);
  821. demorect(box, "Layout( UI_HFILL )", 0.15f, 0, UI_HFILL, T, T, M, 0, M, M);
  822. demorect(box, "Layout( UI_VFILL )", 0.2f, 0, UI_VFILL, T, T, 0, 0, 0, M);
  823. demorect(box, "Layout( UI_VFILL )", 0.2f, 0, UI_VFILL, T, T, 0, 0, 0, M);
  824. demorect(box, "Layout( UI_VFILL )", 0.2f, 0, UI_VFILL, T, T, 0, 0, 0, M);
  825. demorect(box, "Layout( UI_RIGHT )", 0.25f, 0, UI_RIGHT, T, T, 0, 0, M, M);
  826. }
  827. }
  828. void fill_wrap_row_box(int box) {
  829. const int M = 5;
  830. const int S = 100;
  831. const int T = 50;
  832. srand(303);
  833. for (int i = 0; i < 20; ++i) {
  834. float hue = (float)(rand()%360)/360.0f;
  835. int width = 10 + (rand()%5)*10;
  836. int u;
  837. switch(rand()%4) {
  838. default: break;
  839. case 0: {
  840. u = demorect(box, "Layout( UI_TOP )", hue, 0, UI_TOP, width, T, M, M, M, M);
  841. } break;
  842. case 1: {
  843. u = demorect(box, "Layout( UI_VCENTER )", hue, 0, UI_VCENTER, width, T/2, M, M, M, M);
  844. } break;
  845. case 2: {
  846. u = demorect(box, "Layout( UI_VFILL )", hue, 0, UI_VFILL, width, T, M, M, M, M);
  847. } break;
  848. case 3: {
  849. u = demorect(box, "Layout( UI_DOWN )", hue, 0, UI_DOWN, width, T/2, M, M, M, M);
  850. } break;
  851. }
  852. if (rand()%10 == 0)
  853. uiSetLayout(u, uiGetLayout(u)|UI_BREAK);
  854. }
  855. }
  856. void fill_wrap_column_box(int box) {
  857. const int M = 5;
  858. const int S = 100;
  859. const int T = 50;
  860. srand(303);
  861. for (int i = 0; i < 20; ++i) {
  862. float hue = (float)(rand()%360)/360.0f;
  863. int height = 10 + (rand()%5)*10;
  864. int u;
  865. switch(rand()%4) {
  866. default: break;
  867. case 0: {
  868. u = demorect(box, "Layout( UI_LEFT )", hue, 0, UI_LEFT, T, height, M, M, M, M);
  869. } break;
  870. case 1: {
  871. u = demorect(box, "Layout( UI_HCENTER )", hue, 0, UI_HCENTER, T/2, height, M, M, M, M);
  872. } break;
  873. case 2: {
  874. u = demorect(box, "Layout( UI_HFILL )", hue, 0, UI_HFILL, T, height, M, M, M, M);
  875. } break;
  876. case 3: {
  877. u = demorect(box, "Layout( UI_RIGHT )", hue, 0, UI_RIGHT, T/2, height, M, M, M, M);
  878. } break;
  879. }
  880. if (rand()%10 == 0)
  881. uiSetLayout(u, uiGetLayout(u)|UI_BREAK);
  882. }
  883. }
  884. void build_wrapdemo(int parent) {
  885. int col = uiItem();
  886. uiInsert(parent, col);
  887. uiSetBox(col, UI_COLUMN);
  888. uiSetLayout(col, UI_FILL);
  889. const int M = 5;
  890. const int S = 100;
  891. const int T = 50;
  892. int box;
  893. box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_START )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP | UI_START, UI_HFILL | UI_TOP, 0, 0, M, M, M, M);
  894. fill_wrap_row_box(box);
  895. box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_MIDDLE )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP, UI_HFILL | UI_TOP, 0, 0, M, M, M, M);
  896. fill_wrap_row_box(box);
  897. box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_END )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP | UI_END, UI_HFILL | UI_TOP, 0, 0, M, M, M, M);
  898. fill_wrap_row_box(box);
  899. box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_JUSTIFY )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP | UI_JUSTIFY, UI_HFILL | UI_TOP, 0, 0, M, M, M, M);
  900. fill_wrap_row_box(box);
  901. box = demorect(col, "Box( UI_COLUMN | UI_WRAP | UI_START )\nLayout( UI_LEFT | UI_VFILL )", 0.6f, UI_COLUMN | UI_WRAP | UI_START, UI_LEFT | UI_VFILL, 0, 0, M, M, M, M);
  902. fill_wrap_column_box(box);
  903. }
  904. int add_menu_option(int parent, const char *name, int *choice) {
  905. int opt = radio(-1, name, choice);
  906. uiInsert(parent, opt);
  907. uiSetLayout(opt, UI_HFILL|UI_TOP);
  908. uiSetMargins(opt, 1, 1, 1, 1);
  909. return opt;
  910. }
  911. void draw(NVGcontext *vg, float w, float h) {
  912. bndBackground(vg, 0, 0, w, h);
  913. // some OUI stuff
  914. uiBeginLayout();
  915. int root = panel();
  916. // position root element
  917. uiSetSize(0,w,h);
  918. ((UIData*)uiGetHandle(root))->handler = roothandler;
  919. uiSetEvents(root, UI_SCROLL|UI_BUTTON0_DOWN);
  920. uiSetBox(root, UI_COLUMN);
  921. static int choice = -1;
  922. int menu = uiItem();
  923. uiSetLayout(menu, UI_HFILL|UI_TOP);
  924. uiSetBox(menu, UI_ROW);
  925. uiInsert(root, menu);
  926. int opt_blendish_demo = add_menu_option(menu, "Blendish Demo", &choice);
  927. int opt_oui_demo = add_menu_option(menu, "OUI Demo", &choice);
  928. int opt_layouts = add_menu_option(menu, "UI_LAYOUT", &choice);
  929. int opt_row = add_menu_option(menu, "UI_ROW", &choice);
  930. int opt_column = add_menu_option(menu, "UI_COLUMN", &choice);
  931. int opt_wrap = add_menu_option(menu, "UI_WRAP", &choice);
  932. if (choice < 0)
  933. choice = opt_blendish_demo;
  934. int content = uiItem();
  935. uiSetLayout(content, UI_FILL);
  936. uiInsert(root, content);
  937. if (choice == opt_blendish_demo) {
  938. int democontent = uiItem();
  939. uiSetLayout(democontent, UI_FILL);
  940. uiInsert(content, democontent);
  941. UIData *data = (UIData *)uiAllocHandle(democontent, sizeof(UIData));
  942. data->handler = 0;
  943. data->subtype = ST_DEMOSTUFF;
  944. } else if (choice == opt_oui_demo) {
  945. int democontent = uiItem();
  946. uiSetLayout(democontent, UI_TOP);
  947. uiSetSize(democontent, 250, 0);
  948. uiInsert(content, democontent);
  949. build_democontent(democontent);
  950. } else if (choice == opt_layouts) {
  951. build_layoutdemo(content);
  952. } else if (choice == opt_row) {
  953. build_rowdemo(content);
  954. } else if (choice == opt_column) {
  955. build_columndemo(content);
  956. } else if (choice == opt_wrap) {
  957. build_wrapdemo(content);
  958. }
  959. uiEndLayout();
  960. drawUI(vg, 0, BND_CORNER_NONE);
  961. #if 0
  962. for (int i = 0; i < uiGetLastItemCount(); ++i) {
  963. if (uiRecoverItem(i) == -1) {
  964. UIitem *pitem = uiLastItemPtr(i);
  965. nvgBeginPath(vg);
  966. nvgRect(vg,pitem->margins[0],pitem->margins[1],pitem->size[0],pitem->size[1]);
  967. nvgStrokeWidth(vg, 2);
  968. nvgStrokeColor(vg, nvgRGBAf(1.0f,0.0f,0.0f,0.5f));
  969. nvgStroke(vg);
  970. }
  971. }
  972. #endif
  973. if (choice == opt_blendish_demo) {
  974. UIvec2 cursor = uiGetCursor();
  975. cursor.x -= w/2;
  976. cursor.y -= h/2;
  977. if (abs(cursor.x) > (w/3)) {
  978. bndJoinAreaOverlay(vg, 0, 0, w, h, 0, (cursor.x > 0));
  979. } else if (abs(cursor.y) > (h/3)) {
  980. bndJoinAreaOverlay(vg, 0, 0, w, h, 1, (cursor.y > 0));
  981. }
  982. }
  983. uiProcess((int)(glfwGetTime()*1000.0));
  984. }
  985. ////////////////////////////////////////////////////////////////////////////////
  986. void errorcb(int error, const char* desc)
  987. {
  988. printf("GLFW error %d: %s\n", error, desc);
  989. }
  990. static void mousebutton(GLFWwindow *window, int button, int action, int mods) {
  991. NVG_NOTUSED(window);
  992. switch(button) {
  993. case 1: button = 2; break;
  994. case 2: button = 1; break;
  995. }
  996. uiSetButton(button, mods, (action==GLFW_PRESS)?1:0);
  997. }
  998. static void cursorpos(GLFWwindow *window, double x, double y) {
  999. NVG_NOTUSED(window);
  1000. uiSetCursor((int)x,(int)y);
  1001. }
  1002. static void scrollevent(GLFWwindow *window, double x, double y) {
  1003. NVG_NOTUSED(window);
  1004. uiSetScroll((int)x, (int)y);
  1005. }
  1006. static void charevent(GLFWwindow *window, unsigned int value) {
  1007. NVG_NOTUSED(window);
  1008. uiSetChar(value);
  1009. }
  1010. static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
  1011. {
  1012. NVG_NOTUSED(scancode);
  1013. if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
  1014. glfwSetWindowShouldClose(window, GL_TRUE);
  1015. uiSetKey(key, mods, action);
  1016. }
  1017. int main()
  1018. {
  1019. GLFWwindow* window;
  1020. UIcontext *uictx;
  1021. uictx = uiCreateContext(4096, 1<<20);
  1022. uiMakeCurrent(uictx);
  1023. uiSetHandler(ui_handler);
  1024. if (!glfwInit()) {
  1025. printf("Failed to init GLFW.");
  1026. return -1;
  1027. }
  1028. glfwSetErrorCallback(errorcb);
  1029. #ifndef _WIN32 // don't require this on win32, and works with more cards
  1030. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  1031. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
  1032. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  1033. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  1034. #endif
  1035. glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
  1036. window = glfwCreateWindow(650, 650, "OUI Blendish Demo", NULL, NULL);
  1037. if (!window) {
  1038. glfwTerminate();
  1039. return -1;
  1040. }
  1041. glfwSetKeyCallback(window, key);
  1042. glfwSetCharCallback(window, charevent);
  1043. glfwSetCursorPosCallback(window, cursorpos);
  1044. glfwSetMouseButtonCallback(window, mousebutton);
  1045. glfwSetScrollCallback(window, scrollevent);
  1046. glfwMakeContextCurrent(window);
  1047. #ifdef NANOVG_GLEW
  1048. glewExperimental = GL_TRUE;
  1049. if(glewInit() != GLEW_OK) {
  1050. printf("Could not init glew.\n");
  1051. return -1;
  1052. }
  1053. // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
  1054. glGetError();
  1055. #endif
  1056. //_vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
  1057. _vg = nvgCreateGL3(NVG_ANTIALIAS);
  1058. if (_vg == NULL) {
  1059. printf("Could not init nanovg.\n");
  1060. return -1;
  1061. }
  1062. init(_vg);
  1063. printf("sizeof(UIitem)=%lu\n", sizeof(UIitem));
  1064. glfwSwapInterval(0);
  1065. glfwSetTime(0);
  1066. double c = 0.0;
  1067. int total = 0;
  1068. int peak_items = 0;
  1069. unsigned int peak_alloc = 0;
  1070. while (!glfwWindowShouldClose(window))
  1071. {
  1072. double mx, my;
  1073. int winWidth, winHeight;
  1074. int fbWidth, fbHeight;
  1075. float pxRatio;
  1076. glfwGetCursorPos(window, &mx, &my);
  1077. glfwGetWindowSize(window, &winWidth, &winHeight);
  1078. glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
  1079. // Calculate pixel ration for hi-dpi devices.
  1080. pxRatio = (float)fbWidth / (float)winWidth;
  1081. // Update and render
  1082. glViewport(0, 0, fbWidth, fbHeight);
  1083. glClearColor(0,0,0,1);
  1084. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  1085. double t = glfwGetTime();
  1086. nvgBeginFrame(_vg, winWidth, winHeight, pxRatio);
  1087. draw(_vg, winWidth, winHeight);
  1088. peak_items = (peak_items > uiGetItemCount())?peak_items:uiGetItemCount();
  1089. peak_alloc = (peak_alloc > uiGetAllocSize())?peak_alloc:uiGetAllocSize();
  1090. nvgEndFrame(_vg);
  1091. double t2 = glfwGetTime();
  1092. c += (t2 - t);
  1093. total++;
  1094. if (total > (1*60)) {
  1095. printf("%fms\n", (c / (double)total)*1000.0);
  1096. total = 0;
  1097. c = 0.0;
  1098. }
  1099. glfwSwapBuffers(window);
  1100. glfwPollEvents();
  1101. }
  1102. printf("Peak item count: %i (%lu bytes)\nPeak allocated handles: %u bytes\n",
  1103. peak_items, peak_items * sizeof(UIitem), peak_alloc);
  1104. uiDestroyContext(uictx);
  1105. nvgDeleteGL3(_vg);
  1106. glfwTerminate();
  1107. return 0;
  1108. }