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.

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