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.

1246 lines
40KB

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