glui.h 95.3 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614
/****************************************************************************

  GLUI User Interface Toolkit
  ---------------------------

     glui.h - Main (and only) external header for 
        GLUI User Interface Toolkit

          --------------------------------------------------

  Copyright (c) 1998 Paul Rademacher

  WWW:    http://sourceforge.net/projects/glui/
  Forums: http://sourceforge.net/forum/?group_id=92496

  This software is provided 'as-is', without any express or implied 
  warranty. In no event will the authors be held liable for any damages 
  arising from the use of this software. 

  Permission is granted to anyone to use this software for any purpose, 
  including commercial applications, and to alter it and redistribute it 
  freely, subject to the following restrictions: 

  1. The origin of this software must not be misrepresented; you must not 
  claim that you wrote the original software. If you use this software 
  in a product, an acknowledgment in the product documentation would be 
  appreciated but is not required. 
  2. Altered source versions must be plainly marked as such, and must not be 
  misrepresented as being the original software. 
  3. This notice may not be removed or altered from any source distribution. 

*****************************************************************************/

#ifndef GLUI_GLUI_H
#define GLUI_GLUI_H

// Having stdlib here first fixes some 'exit() redefined' errors on MSVC.NET
// that come from old GLUT headers.
#include <cstdlib>
#include <iterator> //added for VS2010 compatability

#if defined(GLUI_FREEGLUT)

  // FreeGLUT does not yet work perfectly with GLUI
  //  - use at your own risk.
  
  #include <GL/freeglut.h>

#elif defined(GLUI_OPENGLUT)

  // OpenGLUT does not yet work properly with GLUI
  //  - use at your own risk.
  
  #include <GL/openglut.h>

#else 

  #ifdef __APPLE__
  #include <GLUT/glut.h>
  #else
  #include <GL/glut.h>
  #endif

#endif

#include <cstdio>
#include <cstring>
#include <string>
#include <vector>

/* GLUI API shared library export/import declarations. */
#if defined(_WIN32)
# ifdef GLUI_BUILDING_LIB
#  ifdef GLUIDLL
#   define GLUIAPI __declspec(dllexport)
#  else
#   define GLUIAPI
#  endif
# else
#  ifdef GLUIDLL
#   define GLUIAPI __declspec(dllimport)
#  else
#   define GLUIAPI
#  endif
# endif
#else
#define GLUIAPI
#endif


#define GLUI_VERSION 2.36f    /********** Current version **********/

/* We do it to avoid confusion between x86 and x64 */
#define GLUI_NO_LIB_PRAGMA

#if defined(_WIN32)
#  if !defined(GLUI_NO_LIB_PRAGMA) && !defined(GLUI_BUILDING_LIB)
// Link automatically with GLUI library
#    if defined GLUIDLL  // define this when using glui dynamic library
#      pragma comment(lib, "glui32dll.lib")
#    else
// EG: Removed because for debug builds we want a different lib
//#      pragma comment(lib, "glui32.lib")  
#    endif
#  endif
#endif


/********** List of GLUT callbacks ********/

enum GLUI_Glut_CB_Types 
{ 
    GLUI_GLUT_RESHAPE,
    GLUI_GLUT_KEYBOARD,
    GLUI_GLUT_DISPLAY,
    GLUI_GLUT_MOUSE,
    GLUI_GLUT_MOTION,
    GLUI_GLUT_SPECIAL,
    GLUI_GLUT_PASSIVE_MOTION,  
    GLUI_GLUT_ENTRY,
    GLUI_GLUT_VISIBILITY  
};

/********* Constants for window placement **********/

#define GLUI_XOFF                       6
#define GLUI_YOFF                       6
#define GLUI_ITEMSPACING                3
#define GLUI_CHECKBOX_SIZE             13
#define GLUI_RADIOBUTTON_SIZE          13
#define GLUI_BUTTON_SIZE               20
#define GLUI_STATICTEXT_SIZE           13
#define GLUI_SEPARATOR_HEIGHT           8
#define GLUI_DEFAULT_CONTROL_WIDTH    100
#define GLUI_DEFAULT_CONTROL_HEIGHT    13 
#define GLUI_EDITTEXT_BOXINNERMARGINX   3
#define GLUI_EDITTEXT_HEIGHT           20
#define GLUI_EDITTEXT_WIDTH           130
#define GLUI_EDITTEXT_MIN_INT_WIDTH    35
#define GLUI_EDITTEXT_MIN_TEXT_WIDTH   50
#define GLUI_PANEL_NAME_DROP            8
#define GLUI_PANEL_EMBOSS_TOP           4
/* #define GLUI_ROTATION_WIDTH         60 */
/* #define GLUI_ROTATION_HEIGHT        78 */
#define GLUI_ROTATION_WIDTH            50
#define GLUI_ROTATION_HEIGHT           (GLUI_ROTATION_WIDTH+18)
#define GLUI_MOUSE_INTERACTION_WIDTH   50
#define GLUI_MOUSE_INTERACTION_HEIGHT  (GLUI_MOUSE_INTERACTION_WIDTH)+18

/** Different panel control types **/
#define GLUI_PANEL_NONE      0
#define GLUI_PANEL_EMBOSSED  1
#define GLUI_PANEL_RAISED    2

/**  Max # of els in control's float_array  **/
#define GLUI_DEF_MAX_ARRAY  30

/********* The control's 'active' behavior *********/
#define GLUI_CONTROL_ACTIVE_MOUSEDOWN       1
#define GLUI_CONTROL_ACTIVE_PERMANENT       2

/********* Control alignment types **********/
#define GLUI_ALIGN_CENTER   1
#define GLUI_ALIGN_RIGHT    2
#define GLUI_ALIGN_LEFT     3

/********** Limit types - how to limit spinner values *********/
#define GLUI_LIMIT_NONE    0
#define GLUI_LIMIT_CLAMP   1
#define GLUI_LIMIT_WRAP    2

/********** Translation control types ********************/
#define GLUI_TRANSLATION_XY 0
#define GLUI_TRANSLATION_Z  1
#define GLUI_TRANSLATION_X  2
#define GLUI_TRANSLATION_Y  3

#define GLUI_TRANSLATION_LOCK_NONE 0
#define GLUI_TRANSLATION_LOCK_X    1
#define GLUI_TRANSLATION_LOCK_Y    2

/********** How was a control activated? *****************/
#define GLUI_ACTIVATE_MOUSE 1
#define GLUI_ACTIVATE_TAB   2

/********** What type of live variable does a control have? **********/
#define GLUI_LIVE_NONE          0
#define GLUI_LIVE_INT           1
#define GLUI_LIVE_FLOAT         2
#define GLUI_LIVE_TEXT          3
#define GLUI_LIVE_STRING        6
#define GLUI_LIVE_DOUBLE        4
#define GLUI_LIVE_FLOAT_ARRAY   5

/************* Textbox and List Defaults - JVK ******************/
#define GLUI_TEXTBOX_HEIGHT          130
#define GLUI_TEXTBOX_WIDTH           130
#define GLUI_LIST_HEIGHT             130
#define GLUI_LIST_WIDTH              130
#define GLUI_DOUBLE_CLICK              1
#define GLUI_SINGLE_CLICK              0
#define GLUI_TAB_WIDTH                50 /* In pixels */
#define GLUI_TEXTBOX_BOXINNERMARGINX   3
#define GLUI_TEXTBOX_MIN_TEXT_WIDTH   50
#define GLUI_LIST_BOXINNERMARGINX      3
#define GLUI_LIST_MIN_TEXT_WIDTH      50

/*********************** TreePanel Defaults - JVK *****************************/
#define GLUI_TREEPANEL_DEFAULTS               0 // bar, standard bar color
#define GLUI_TREEPANEL_ALTERNATE_COLOR        1 // Alternate between 8 different bar colors
#define GLUI_TREEPANEL_ENABLE_BAR             2 // enable the bar
#define GLUI_TREEPANEL_DISABLE_BAR            4 // disable the bar
#define GLUI_TREEPANEL_DISABLE_DEEPEST_BAR    8 // disable only the deepest bar
#define GLUI_TREEPANEL_CONNECT_CHILDREN_ONLY 16 // disable only the bar of the last child of each root
#define GLUI_TREEPANEL_DISPLAY_HIERARCHY     32 // display some sort of hierachy in the tree node title
#define GLUI_TREEPANEL_HIERARCHY_NUMERICDOT  64 // display hierarchy in 1.3.2 (etc... ) format
#define GLUI_TREEPANEL_HIERARCHY_LEVEL_ONLY 128 // display hierarchy as only the level depth
 
/******************* GLUI Scrollbar Defaults - JVK ***************************/
#define  GLUI_SCROLL_ARROW_WIDTH     16
#define  GLUI_SCROLL_ARROW_HEIGHT    16
#define  GLUI_SCROLL_BOX_MIN_HEIGHT   5
#define  GLUI_SCROLL_BOX_STD_HEIGHT  16
#define  GLUI_SCROLL_STATE_NONE       0
#define  GLUI_SCROLL_STATE_UP         1
#define  GLUI_SCROLL_STATE_DOWN       2
#define  GLUI_SCROLL_STATE_BOTH       3
#define  GLUI_SCROLL_STATE_SCROLL     4
#define  GLUI_SCROLL_DEFAULT_GROWTH_EXP   1.05f
#define  GLUI_SCROLL_VERTICAL         0
#define  GLUI_SCROLL_HORIZONTAL       1


/** Size of the character width hash table for faster lookups. 
  Make sure to keep this a power of two to avoid the slow divide.
  This is also a speed/memory tradeoff; 128 is enough for low ASCII.
*/
#define CHAR_WIDTH_HASH_SIZE 128

/**********  Translation codes  **********/

enum TranslationCodes  
{
    GLUI_TRANSLATION_MOUSE_NONE = 0,
    GLUI_TRANSLATION_MOUSE_UP,
    GLUI_TRANSLATION_MOUSE_DOWN,
    GLUI_TRANSLATION_MOUSE_LEFT,
    GLUI_TRANSLATION_MOUSE_RIGHT,
    GLUI_TRANSLATION_MOUSE_UP_LEFT,
    GLUI_TRANSLATION_MOUSE_UP_RIGHT,
    GLUI_TRANSLATION_MOUSE_DOWN_LEFT,
    GLUI_TRANSLATION_MOUSE_DOWN_RIGHT
};

/************ A string type for us to use **********/

typedef std::string GLUI_String;
GLUIAPI GLUI_String& glui_format_str(GLUI_String &str, const char* fmt, ...);

/********* Pre-declare classes as needed *********/

class GLUI;
class GLUI_Control;
class GLUI_Listbox;
class GLUI_StaticText;
class GLUI_EditText;
class GLUI_Panel;
class GLUI_Spinner;
class GLUI_RadioButton;
class GLUI_RadioGroup;
class GLUI_Glut_Window;
class GLUI_TreePanel;
class GLUI_Scrollbar;
class GLUI_List;

class Arcball;

/*** Flags for GLUI class constructor ***/
#define  GLUI_SUBWINDOW          ((long)(1<<1))
#define  GLUI_SUBWINDOW_TOP      ((long)(1<<2))
#define  GLUI_SUBWINDOW_BOTTOM   ((long)(1<<3))
#define  GLUI_SUBWINDOW_LEFT     ((long)(1<<4))
#define  GLUI_SUBWINDOW_RIGHT    ((long)(1<<5))

/*** Codes for different type of edittext boxes and spinners ***/
#define GLUI_EDITTEXT_TEXT             1
#define GLUI_EDITTEXT_INT              2
#define GLUI_EDITTEXT_FLOAT            3
#define GLUI_SPINNER_INT               GLUI_EDITTEXT_INT
#define GLUI_SPINNER_FLOAT             GLUI_EDITTEXT_FLOAT
#define GLUI_SCROLL_INT                GLUI_EDITTEXT_INT
#define GLUI_SCROLL_FLOAT              GLUI_EDITTEXT_FLOAT
// This is only for deprecated interface
#define GLUI_EDITTEXT_STRING           4

/*** Definition of callbacks ***/
typedef void (*GLUI_Update_CB) (int id);
typedef void (*GLUI_Control_CB)(GLUI_Control *);
typedef void (*Int1_CB)        (int);
typedef void (*Int2_CB)        (int, int);
typedef void (*Int3_CB)        (int, int, int);
typedef void (*Int4_CB)        (int, int, int, int);

/************************************************************/
/**
 Callback Adapter Class                            
    Allows us to support different types of callbacks;
    like a GLUI_Update_CB function pointer--which takes an int;
    and a GLUI_Control_CB function pointer--which takes a GUI_Control object.
*/
class GLUIAPI GLUI_CB
{
public:
  GLUI_CB() : idCB(0),objCB(0) {}
  GLUI_CB(GLUI_Update_CB cb) : idCB(cb),objCB(0) {}
  GLUI_CB(GLUI_Control_CB cb) : idCB(0),objCB(cb) {}
  // (Compiler generated copy constructor)

  /** This control just activated.  Fire our callback.*/
  void operator()(GLUI_Control *ctrl) const;
  bool operator!() const { return !idCB && !objCB; }
  operator bool() const { return !(!(*this)); }
private:
  GLUI_Update_CB idCB;
  GLUI_Control_CB objCB;
};

/************************************************************/
/*                                                          */
/*          Base class, for hierarchical relationships      */
/*                                                          */
/************************************************************/

class GLUI_Control;

/**
 GLUI_Node is a node in a sort of tree of GLUI controls.
 Each GLUI_Node has a list of siblings (in a circular list)
 and a linked list of children.
 
 Everything onscreen is a GLUI_Node--windows, buttons, etc.
 The nodes are traversed for event processing, sizing, redraws, etc.
*/
class GLUIAPI GLUI_Node 
{
    friend class GLUI_Tree;     /* JVK */
    friend class GLUI_Rollout;
    friend class GLUI_Main;

public:
    GLUI_Node();
    virtual ~GLUI_Node() {}

    GLUI_Node *first_sibling();
    GLUI_Node *last_sibling();
    GLUI_Node *prev();
    GLUI_Node *next();

    GLUI_Node *first_child()   { return child_head; }
    GLUI_Node *last_child()    { return child_tail; }
    GLUI_Node *parent()        { return parent_node; }

    /** Link in a new child control */
    virtual int  add_control( GLUI_Control *control );

    void link_this_to_parent_last (GLUI_Node *parent  );
    void link_this_to_parent_first(GLUI_Node *parent  );
    void link_this_to_sibling_next(GLUI_Node *sibling );
    void link_this_to_sibling_prev(GLUI_Node *sibling );
    void unlink();

    void dump( FILE *out, const char *name );

protected:
    static void add_child_to_control(GLUI_Node *parent,GLUI_Control *child);
    GLUI_Node *parent_node;
    GLUI_Node *child_head;
    GLUI_Node *child_tail;
    GLUI_Node *next_sibling;
    GLUI_Node *prev_sibling;
};


/************************************************************/
/*                                                          */
/*                  Standard Bitmap stuff                   */
/*                                                          */
/************************************************************/

enum GLUI_StdBitmaps_Codes 
{
    GLUI_STDBITMAP_CHECKBOX_OFF = 0,
    GLUI_STDBITMAP_CHECKBOX_ON,
    GLUI_STDBITMAP_RADIOBUTTON_OFF,
    GLUI_STDBITMAP_RADIOBUTTON_ON,
    GLUI_STDBITMAP_UP_ARROW,
    GLUI_STDBITMAP_DOWN_ARROW,
    GLUI_STDBITMAP_LEFT_ARROW,
    GLUI_STDBITMAP_RIGHT_ARROW,
    GLUI_STDBITMAP_SPINNER_UP_OFF,
    GLUI_STDBITMAP_SPINNER_UP_ON,
    GLUI_STDBITMAP_SPINNER_DOWN_OFF,
    GLUI_STDBITMAP_SPINNER_DOWN_ON,
    GLUI_STDBITMAP_CHECKBOX_OFF_DIS,    /*** Disactivated control bitmaps ***/
    GLUI_STDBITMAP_CHECKBOX_ON_DIS,
    GLUI_STDBITMAP_RADIOBUTTON_OFF_DIS,
    GLUI_STDBITMAP_RADIOBUTTON_ON_DIS,
    GLUI_STDBITMAP_SPINNER_UP_DIS,
    GLUI_STDBITMAP_SPINNER_DOWN_DIS,
    GLUI_STDBITMAP_LISTBOX_UP,
    GLUI_STDBITMAP_LISTBOX_DOWN,
    GLUI_STDBITMAP_LISTBOX_UP_DIS,
    GLUI_STDBITMAP_NUM_ITEMS
};

/************************************************************/
/*                                                          */
/*                  Class GLUI_Bitmap                       */
/*                                                          */
/************************************************************/

/**
 GLUI_Bitmap is a simple 2D texture map.  It's used
 to represent small textures like checkboxes, arrows, etc.
 via the GLUI_StdBitmaps class.
*/
class GLUIAPI GLUI_Bitmap 
{
    friend class GLUI_StdBitmaps;

public:
    GLUI_Bitmap();
    ~GLUI_Bitmap();

    /** Create bitmap from greyscale byte image */
    void init_grey(unsigned char *array);
    
    /** Create bitmap from color int image */
    void init(int *array);

private:
    /** RGB pixel data */
    unsigned char *pixels;
    int            w, h;
};


/************************************************************/
/*                                                          */
/*                  Class GLUI_StdBitmap                    */
/*                                                          */
/************************************************************/

/**
 Keeps an array of GLUI_Bitmap objects to represent all the 
 images used in the UI: checkboxes, arrows, etc.
*/
class GLUIAPI GLUI_StdBitmaps
{
public:
    GLUI_StdBitmaps(); 
    ~GLUI_StdBitmaps();

    /** Return the width (in pixels) of the n'th standard bitmap. */
    int  width (int n) const;
    /** Return the height (in pixels) of the n'th standard bitmap. */
    int  height(int n) const;

    /** Draw the n'th standard bitmap (one of the enums
       listed in GLUI_StdBitmaps_Codes) at pixel corner (x,y). 
    */
    void draw(int n, int x, int y) const;

private:
    GLUI_Bitmap bitmaps[GLUI_STDBITMAP_NUM_ITEMS];
};

/************************************************************/
/*                                                          */
/*                     Master GLUI Class                    */
/*                                                          */
/************************************************************/

/**
 The master manages our interaction with GLUT.
 There's only one GLUI_Master_Object.
*/
class GLUIAPI GLUI_Master_Object 
{

    friend void glui_idle_func();
  
public:

    GLUI_Master_Object();
    ~GLUI_Master_Object();

    GLUI_Node     gluis;
    GLUI_Control *active_control, *curr_left_button_glut_menu;
    GLUI         *active_control_glui;
    int           glui_id_counter;

    GLUI_Glut_Window   *find_glut_window( int window_id );

    void           set_glutIdleFunc(void (*f)(void));

    /**************
    void (*glut_keyboard_CB)(unsigned char, int, int);
    void (*glut_reshape_CB)(int, int);
    void (*glut_special_CB)(int, int, int);
    void (*glut_mouse_CB)(int,int,int,int);

    void (*glut_passive_motion_CB)(int,int);
    void (*glut_visibility_CB)(int);
    void (*glut_motion_CB)(int,int);
    void (*glut_display_CB)(void);
    void (*glut_entry_CB)(int);
    **********/

    void  set_left_button_glut_menu_control( GLUI_Control *control );

    /********** GLUT callthroughs **********/
    /* These are the glut callbacks that we do not handle */

    void set_glutReshapeFunc (void (*f)(int width, int height));
    void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y));
    void set_glutSpecialFunc (void (*f)(int key, int x, int y));
    void set_glutMouseFunc   (void (*f)(int, int, int, int ));

    void set_glutDisplayFunc(void (*f)(void)) {glutDisplayFunc(f);}
    void set_glutTimerFunc(unsigned int millis, void (*f)(int value), int value)
    { ::glutTimerFunc(millis,f,value);}
    void set_glutOverlayDisplayFunc(void(*f)(void)){glutOverlayDisplayFunc(f);}
    void set_glutSpaceballMotionFunc(Int3_CB f)  {glutSpaceballMotionFunc(f);}
    void set_glutSpaceballRotateFunc(Int3_CB f)  {glutSpaceballRotateFunc(f);}
    void set_glutSpaceballButtonFunc(Int2_CB f)  {glutSpaceballButtonFunc(f);}
    void set_glutTabletMotionFunc(Int2_CB f)        {glutTabletMotionFunc(f);}
    void set_glutTabletButtonFunc(Int4_CB f)        {glutTabletButtonFunc(f);}
    /*    void set_glutWindowStatusFunc(Int1_CB f)        {glutWindowStatusFunc(f);} */
    void set_glutMenuStatusFunc(Int3_CB f)            {glutMenuStatusFunc(f);}
    void set_glutMenuStateFunc(Int1_CB f)              {glutMenuStateFunc(f);}
    void set_glutButtonBoxFunc(Int2_CB f)              {glutButtonBoxFunc(f);}
    void set_glutDialsFunc(Int2_CB f)                      {glutDialsFunc(f);}  
  

    GLUI          *create_glui( const char *name, long flags=0, int x=-1, int y=-1 ); 
    GLUI          *create_glui_subwindow( int parent_window, long flags=0 );
    GLUI          *find_glui_by_window_id( int window_id );
    void           get_viewport_area( int *x, int *y, int *w, int *h );
    void           auto_set_viewport();
    void           close_all();
    void           sync_live_all();

    void           reshape();

    float          get_version() { return GLUI_VERSION; }

    void glui_setIdleFuncIfNecessary(void);

private:
    GLUI_Node     glut_windows;
    void (*glut_idle_CB)(void);

    void          add_cb_to_glut_window(int window,int cb_type,void *cb);
};

/**
 This is the only GLUI_Master_Object in existence.
*/
extern GLUIAPI GLUI_Master_Object GLUI_Master;

/************************************************************/
/*                                                          */
/*              Class for managing a GLUT window            */
/*                                                          */
/************************************************************/

/**
 A top-level window.  The GLUI_Master GLUT callback can route events
 to the callbacks in this class, for arbitrary use by external users.
 (see GLUI_Master_Object::set_glutKeyboardFunc).
 
 This entire approach seems to be superceded by the "subwindow" flavor
 of GLUI.
*/
class GLUIAPI GLUI_Glut_Window : public GLUI_Node 
{
public:
    GLUI_Glut_Window();

    int    glut_window_id;

    /*********** Pointers to GLUT callthrough functions *****/
    void (*glut_keyboard_CB)(unsigned char, int, int);
    void (*glut_special_CB)(int, int, int);
    void (*glut_reshape_CB)(int, int);
    void (*glut_passive_motion_CB)(int,int);
    void (*glut_mouse_CB)(int,int,int,int);
    void (*glut_visibility_CB)(int);
    void (*glut_motion_CB)(int,int);
    void (*glut_display_CB)(void);
    void (*glut_entry_CB)(int);
};

/************************************************************/
/*                                                          */
/*       Main Window GLUI class (not user-level)            */
/*                                                          */
/************************************************************/

/**
  A GLUI_Main handles GLUT events for one window, routing them to the 
  appropriate controls.  The central user-visible "GLUI" class 
  inherits from this class; users should not allocate GLUT_Main objects.
  
  There's a separate GLUI_Main object for:
  	- Each top-level window with GUI stuff in it.
	- Each "subwindow" of another top-level window.

  All the GLUI_Main objects are listed in GLUI_Master.gluis.
  A better name for this class might be "GLUI_Environment";
  this class provides the window-level context for every control.
*/
class GLUIAPI GLUI_Main : public GLUI_Node 
{
    /********** Friend classes *************/

    friend class GLUI_Control;
    friend class GLUI_Rotation;
    friend class GLUI_Translation;
    friend class GLUI;
    friend class GLUI_Master_Object;

    /*********** Friend functions **********/

    friend void glui_mouse_func(int button, int state, int x, int y);
    friend void glui_keyboard_func(unsigned char key, int x, int y);
    friend void glui_special_func(int key, int x, int y);
    friend void glui_passive_motion_func(int x, int y);
    friend void glui_reshape_func( int w, int h );
    friend void glui_visibility_func(int state);
    friend void glui_motion_func(int x, int y);
    friend void glui_entry_func(int state);
    friend void glui_display_func( void );
    friend void glui_idle_func(void);

    friend void glui_parent_window_reshape_func( int w, int h );
    friend void glui_parent_window_keyboard_func( unsigned char, int, int );
    friend void glui_parent_window_special_func( int, int, int );
    friend void glui_parent_window_mouse_func( int, int, int, int );

protected:
    /*** Variables ***/
    int           main_gfx_window_id;
    int           mouse_button_down;
    int           glut_window_id;
    int           top_level_glut_window_id;
    GLUI_Control *active_control;
    GLUI_Control *mouse_over_control;
    GLUI_Panel   *main_panel;
    enum buffer_mode_t {
      buffer_front=1, ///< Draw updated controls directly to screen.
      buffer_back=2   ///< Double buffering: postpone updates until next redraw.
    };
    buffer_mode_t buffer_mode; ///< Current drawing mode
    int           curr_cursor;
    int           w, h;
    long          flags; 
    bool          closing;
    int           parent_window;
    int           glui_id;

    /********** Misc functions *************/

    GLUI_Control  *find_control( int x, int y );
    GLUI_Control  *find_next_control( GLUI_Control *control );
    GLUI_Control  *find_next_control_rec( GLUI_Control *control );
    GLUI_Control  *find_next_control_( GLUI_Control *control );
    GLUI_Control  *find_prev_control( GLUI_Control *control );
    void           create_standalone_window( const char *name, int x=-1, int y=-1 );
    void           create_subwindow( int parent,int window_alignment );
    void           setup_default_glut_callbacks( void );

    void           mouse(int button, int state, int x, int y);
    void           keyboard(unsigned char key, int x, int y);
    void           special(int key, int x, int y);
    void           passive_motion(int x, int y);
    void           reshape( int w, int h );
    void           visibility(int state);
    void           motion(int x, int y);
    void           entry(int state);
    void           display( void );
    void           idle(void);
    int            needs_idle(void);

    void (*glut_mouse_CB)(int, int, int, int);
    void (*glut_keyboard_CB)(unsigned char, int, int);
    void (*glut_special_CB)(int, int, int);
    void (*glut_reshape_CB)(int, int);


    /*********** Controls ************/

    virtual int    add_control( GLUI_Node *parent, GLUI_Control *control );


    /********** Constructors and Destructors ***********/

    GLUI_Main( void );

public:
    GLUI_StdBitmaps  std_bitmaps;
    GLUI_String      window_name;
    unsigned char    bkgd_color[3];
    float            bkgd_color_f[3];

    void            *font;
    int              curr_modifiers;

    void         adjust_glut_xy( int &/*x*/, int &y ) { y = h-y; }
    void         activate_control( GLUI_Control *control, int how );
    void         align_controls( GLUI_Control *control );
    void         deactivate_current_control( void );
    
    /** Draw a 3D-look pushed-out box around this rectangle */
    void         draw_raised_box( int x, int y, int w, int h );
    /** Draw a 3D-look pushed-in box around this rectangle */
    void         draw_lowered_box( int x, int y, int w, int h );
    
    /** Return true if this control should redraw itself immediately (front buffer);
       Or queue up a redraw and return false if it shouldn't (back buffer).
    */
    bool         should_redraw_now(GLUI_Control *ctl);
    
    /** Switch to the appropriate draw buffer now.  Returns the old draw buffer. 
       This routine should probably only be called from inside the GLUI_DrawingSentinal,
       in glui_internal_control.h
    */
    int          set_current_draw_buffer();
    /** Go back to using this draw buffer.  Undoes set_current_draw_buffer. */
    void         restore_draw_buffer( int buffer_state );
    
    /** Pack, resize the window, and redraw all the controls. */
    void         refresh();
    
    /** Redraw the main graphics window */
    void         post_update_main_gfx();
  
    /** Recompute the sizes and positions of all controls */
    void         pack_controls();
    
    void         close_internal();
    void         check_subwindow_position();
    void         set_ortho_projection();
    void         set_viewport();
    int          get_glut_window_id( void ) { return glut_window_id; } /* JVK */
};

/************************************************************/
/*                                                          */
/*       GLUI_Control: base class for all controls          */
/*                                                          */
/************************************************************/

/**
 All the GUI objects inherit from GLUI_Control: buttons,
 checkboxes, labels, edit boxes, scrollbars, etc.
 Most of the work of this class is in routing events,
 like keystrokes, mouseclicks, redraws, and sizing events.
 
 Yes, this is a huge and hideous class.  It needs to be 
 split up into simpler subobjects.  None of the data members
 should be directly accessed by users (they should be protected,
 not public); only subclasses.
*/
class GLUIAPI GLUI_Control : public GLUI_Node 
{
public:

/** Onscreen coordinates */
    int             w, h;                        /* dimensions of control */
    int             x_abs, y_abs;
    int             x_off, y_off_top, y_off_bot; /* INNER margins, by which child
                                                    controls are indented */
    int             contain_x, contain_y; 
    int             contain_w, contain_h;
    /* if this is a container control (e.g., 
       radiogroup or panel) this indicated dimensions
       of inner area in which controls reside */

/** "activation" for tabbing between controls. */
    int             active_type; ///< "GLUI_CONTROL_ACTIVE_..."
    bool            active;       ///< If true, we've got the focus
    bool            can_activate; ///< If false, remove from tab order.
    bool            spacebar_mouse_click; ///< Spacebar simulates click.
    
/** Callbacks */
    long            user_id;  ///< Integer to pass to callback function.
    GLUI_CB         callback; ///< User callback function, or NULL.

/** Variable value storage */
    float           float_val;        /**< Our float value */
    int             int_val;          /**< Our integer value */
    float           float_array_val[GLUI_DEF_MAX_ARRAY];
    int             float_array_size;
    GLUI_String     text;       /**< The text inside this control */
    
/** "Live variable" updating */
    void           *ptr_val;          /**< A pointer to the user's live variable value */
    int             live_type;
    bool            live_inited;
    /* These variables store the last value that live variable was known to have. */
    int             last_live_int;  
    float           last_live_float;
    GLUI_String     last_live_text;
    float           last_live_float_array[GLUI_DEF_MAX_ARRAY];
    
/** Properties of our control */    
    GLUI           *glui;       /**< Our containing event handler (NEVER NULL during event processing!) */
    bool            is_container;  /**< Is this a container class (e.g., panel) */
    int             alignment;
    bool            enabled;    /**< Is this control grayed out? */
    GLUI_String     name;       /**< The name of this control */
    void           *font;       /**< Our glutbitmap font */
    bool            collapsible, is_open;
    GLUI_Node       collapsed_node;
    bool            hidden; /* Collapsed controls (and children) are hidden */
    int             char_widths[CHAR_WIDTH_HASH_SIZE][2]; /* Character width hash table */

public:
    /*** Get/Set values ***/
    virtual void   set_name( const char *string );
    virtual void   set_int_val( int new_int )         { int_val = new_int; output_live(true); }
    virtual void   set_float_val( float new_float )   { float_val = new_float; output_live(true); }
    virtual void   set_ptr_val( void *new_ptr )       { ptr_val = new_ptr; output_live(true); }
    virtual void   set_float_array_val( float *array_ptr );

    virtual float  get_float_val( void )              { return float_val; }
    virtual int    get_int_val( void )                { return int_val; }
    virtual void   get_float_array_val( float *array_ptr );
    virtual int    get_id( void ) const { return user_id; }
    virtual void   set_id( int id ) { user_id=id; }

    virtual int mouse_down_handler( int /*local_x*/, int /*local_y*/ )						{ return false; }
    virtual int mouse_up_handler( int /*local_x*/, int /*local_y*/, bool /*inside*/ )       { return false; }
    virtual int mouse_held_down_handler( int /*local_x*/, int /*local_y*/, bool /*inside*/)	{ return false; }
    virtual int key_handler( unsigned char /*key*/, int /*modifiers*/ )						{ return false; }
    virtual int special_handler( int /*key*/,int /*modifiers*/ )							{ return false; }

    virtual void update_size( void )     { }
    virtual void idle( void )            { }
    virtual int  mouse_over( int /*state*/, int /*x*/, int /*y*/ ) { return false; }

    virtual void enable( void ); 
    virtual void disable( void );
    virtual void activate( int /*how*/ )     { active = true; }
    virtual void deactivate( void )     { active = false; }

    /** Hide (shrink into a rollout) and unhide (expose from a rollout) */
    void         hide_internal( int recurse );
    void         unhide_internal( int recurse );

    /** Return true if it currently makes sense to draw this class. */
    int          can_draw( void ) { return (glui != NULL && hidden == false); }

    /** Redraw this control.
       In single-buffering mode (drawing to GL_FRONT), this is just 
           a call to translate_and_draw_front (after a can_draw() check).
       In double-buffering mode (drawing to GL_BACK), this queues up 
          a redraw and returns false, since you shouldn't draw yet.
    */
    void          redraw(void);
    
    /** Redraw everybody in our window. */
    void         redraw_window(void);

    virtual void align( void );
    void         pack( int x, int y );    /* Recalculate positions and offsets */
    void         pack_old( int x, int y );    
    void         draw_recursive( int x, int y );
    int          set_to_glut_window( void );
    void         restore_window( int orig );
    void         translate_and_draw_front( void );
    void         translate_to_origin( void ) 
						{glTranslatef((float)x_abs+.5f,(float)y_abs+.5f,0.0f);}
    virtual void draw( int x, int y )=0;
    void         set_font( void *new_font );
    void        *get_font( void );
    int          string_width( const char *text );
    int          string_width( const GLUI_String &str ) 
    { return string_width(str.c_str()); }
    int          char_width( char c );

    void         draw_name( int x, int y );
    void         draw_box_inwards_outline( int x_min, int x_max, 
                                           int y_min, int y_max );
    void         draw_box( int x_min, int x_max, int y_min, int y_max,
                           float r, float g, float b );
    void         draw_bkgd_box( int x_min, int x_max, int y_min, int y_max );
    void         draw_emboss_box( int x_min, int x_max,int y_min,int y_max);
    void         draw_string( const char *text );
    void         draw_string( const GLUI_String &s ) 
    { draw_string(s.c_str()); }
    void         draw_char( char c );
    void         draw_active_box( int x_min, int x_max, int y_min, int y_max );
    void         set_to_bkgd_color( void );

    void         set_w( int new_w );
    void         set_h( int new_w );
    void         set_alignment( int new_align );
    void         sync_live( int recurse, int draw );  /* Reads live variable */
    void         init_live( void );
    void         output_live( int update_main_gfx );        /** Writes live variable **/
    virtual void set_text( const char * /*t*/ )   {}
    void         execute_callback( void );
    void         get_this_column_dims( int *col_x, int *col_y, 
                                       int *col_w, int *col_h, 
                                       int *col_x_off, int *col_y_off );
    virtual bool needs_idle( void ) const;
    virtual bool wants_tabs() const      { return false; }

    GLUI_Control(void) 
    {
        x_off          = GLUI_XOFF;
        y_off_top      = GLUI_YOFF;
        y_off_bot      = GLUI_YOFF;
        x_abs          = GLUI_XOFF;
        y_abs          = GLUI_YOFF;
        active         = false;
        enabled        = true;
        int_val        = 0;
        last_live_int  = 0;
        float_array_size = 0;
        glui_format_str(name, "Control: %p", this);
        float_val      = 0.0;
        last_live_float = 0.0;
        ptr_val        = NULL;
        glui           = NULL;
        w              = GLUI_DEFAULT_CONTROL_WIDTH;
        h              = GLUI_DEFAULT_CONTROL_HEIGHT;
        font           = NULL;
        active_type    = GLUI_CONTROL_ACTIVE_MOUSEDOWN;
        alignment      = GLUI_ALIGN_LEFT;
        is_container   = false;
        can_activate   = true;         /* By default, you can activate a control */
        spacebar_mouse_click = true;    /* Does spacebar simulate a mouse click? */
        live_type      = GLUI_LIVE_NONE;
        text = "";
        last_live_text == "";
        live_inited    = false;
        collapsible    = false;
        is_open        = true;
        hidden         = false;
        memset(char_widths, -1, sizeof(char_widths)); /* JVK */
        int i;
        for( i=0; i<GLUI_DEF_MAX_ARRAY; i++ )
            float_array_val[i] = last_live_float_array[i] = 0.0;
    }

    virtual ~GLUI_Control();
};

/************************************************************/
/*                                                          */
/*               Button class (container)                   */
/*                                                          */
/************************************************************/
/**
  An onscreen, clickable button--an outlined label that 
  can be clicked.  When clicked, a button
  calls its GLUI_CB callback with its ID.
*/
class GLUIAPI GLUI_Button : public GLUI_Control
{
public:
    bool currently_inside;

    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  key_handler( unsigned char key,int modifiers );

    void draw( int x, int y );
    void draw_pressed( void );
    void draw_text( int sunken );

    void update_size( void );

/**
 Create a new button.
 
  @param parent The panel our object is inside; or the main GLUI object.
  @param name The text inside the button.
  @param id Optional ID number, to pass to the optional callback function.
  @param callback Optional callback function, taking either the int ID or control.
*/
    GLUI_Button( GLUI_Node *parent, const char *name, 
                 int id=-1, GLUI_CB cb=GLUI_CB() );
    GLUI_Button( void ) { common_init(); };

protected:
    void common_init(void) {
        glui_format_str(name, "Button: %p", this );
        h            = GLUI_BUTTON_SIZE;
        w            = 100;
        alignment    = GLUI_ALIGN_CENTER;
        can_activate = true;
    }
};


/************************************************************/
/*                                                          */
/*               Checkbox class (container)                 */
/*                                                          */
/************************************************************/

/**
 A checkbox, which can be checked on or off.  Can be linked
 to an int value, which gets 1 for on and 0 for off.
*/
class GLUIAPI GLUI_Checkbox : public GLUI_Control
{
public:
    int  orig_value;
    bool currently_inside;
    int  text_x_offset;

    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  key_handler( unsigned char key,int modifiers );

    void update_size( void );

    void draw( int x, int y );

    void draw_active_area( void );
    void draw_empty_box( void );
    void set_int_val( int new_val );

/**
 Create a new checkbox object.
 
  @param parent The panel our object is inside; or the main GLUI object.
  @param name Label next to our checkbox.
  @param value_ptr Optional integer value to attach to this checkbox.  When the 
     checkbox is checked or unchecked, *value_ptr will also be changed. ("Live Vars").
  @param id Optional ID number, to pass to the optional callback function.
  @param callback Optional callback function, taking either the int ID or control.
*/
    GLUI_Checkbox(GLUI_Node *parent, const char *name, int *value_ptr=NULL,
                  int id=-1, GLUI_CB callback=GLUI_CB());
    GLUI_Checkbox( void ) { common_init(); }

protected:
    void common_init(void) {
        glui_format_str( name, "Checkbox: %p", this );
        w              = 100;
        h              = GLUI_CHECKBOX_SIZE;
        orig_value     = -1;
        text_x_offset  = 18;
        can_activate   = true;
        live_type      = GLUI_LIVE_INT;   /* This control has an 'int' live var */
    }
};

/************************************************************/
/*                                                          */
/*               Column class                               */
/*                                                          */
/************************************************************/

/**
 A GLUI_Column object separates all previous controls
 from subsequent controls with a vertical bar.
*/
class GLUIAPI GLUI_Column : public GLUI_Control
{
public:
    void draw( int x, int y );

/**
 Create a new column, which separates the previous controls
 from subsequent controls.
 
  @param parent The panel our object is inside; or the main GLUI object.
  @param draw_bar If true, draw a visible bar between new and old controls.
*/
    GLUI_Column( GLUI_Node *parent, int draw_bar = true );
    GLUI_Column( void ) { common_init(); }

protected:
    void common_init() {
        w            = 0;
        h            = 0;
        int_val      = 0;
        can_activate = false;
    }
};


/************************************************************/
/*                                                          */
/*               Panel class (container)                    */
/*                                                          */
/************************************************************/

/**
 A GLUI_Panel contains a group of related controls.
*/
class GLUIAPI GLUI_Panel : public GLUI_Control
{
public:

/**
 Create a new panel.  A panel groups together a set of related controls.
 
  @param parent The outer panel our panel is inside; or the main GLUI object.
  @param name The string name at the top of our panel.
  @param type Optional style to display the panel with--GLUI_PANEL_EMBOSSED by default.
      GLUI_PANEL_RAISED causes the panel to appear higher than the surroundings.
      GLUI_PANEL_NONE causes the panel's outline to be invisible.
*/
    GLUI_Panel( GLUI_Node *parent, const char *name, 
                int type=GLUI_PANEL_EMBOSSED );
    GLUI_Panel() { common_init(); }

    void draw( int x, int y );
    void set_name( const char *text );
    void set_type( int new_type );

    void update_size( void );

protected:
    void common_init( void ) {
        w            = 300;
        h            = GLUI_DEFAULT_CONTROL_HEIGHT + 7;
        int_val      = GLUI_PANEL_EMBOSSED;
        alignment    = GLUI_ALIGN_CENTER;
        is_container = true; 
        can_activate = false;
        name="";
    };
};

/************************************************************/
/*                                                          */
/*               File Browser class (container)             */
/*                         JVK                              */
/************************************************************/

/**
 A list of files the user can select from.
*/
class GLUIAPI GLUI_FileBrowser : public GLUI_Panel
{
public:
/**
 Create a new list of files the user can select from.
 
  @param parent The panel our object is inside; or the main GLUI object.
  @param name Prompt to give to the user at the top of the file browser.
  @param frame_type Optional style to display the panel with--GLUI_PANEL_EMBOSSED by default.
      GLUI_PANEL_RAISED causes the panel to appear higher than the surroundings.
      GLUI_PANEL_NONE causes the panel's outline to be invisible.
  @param id Optional ID number, to pass to the optional callback function.
  @param callback Optional callback function, taking either the int ID or control.
*/
    GLUI_FileBrowser( GLUI_Node *parent, 
                      const char *name,
                      int frame_type = GLUI_PANEL_EMBOSSED,
                      int user_id = -1,
                      GLUI_CB callback = GLUI_CB());

    GLUI_List *list;
    GLUI_String current_dir;

    void fbreaddir(const char *);
    static void dir_list_callback(GLUI_Control*);

    void set_w(int w);
    void set_h(int h);
    const char* get_file() { return file.c_str(); }
    void set_allow_change_dir(int c) { allow_change_dir = c; }

protected:
    void common_init() 
    {
        w            = GLUI_DEFAULT_CONTROL_WIDTH;
        h            = GLUI_DEFAULT_CONTROL_HEIGHT;
        int_val      = GLUI_PANEL_EMBOSSED;
        alignment    = GLUI_ALIGN_CENTER;
        is_container = true; 
        can_activate = false;
        allow_change_dir = true;
        last_item    = -1;
        user_id      = -1;
        name         = "";
        current_dir  = ".";
        file         = "";
    };

private:
    int last_item;
    GLUI_String file;
    int allow_change_dir;

};

/************************************************************/
/*                                                          */
/*               Rollout class (container)                  */
/*                                                          */
/************************************************************/
/**
 A rollout contains a set of controls,
 like a panel, but can be collapsed to just the name.
*/
class GLUIAPI GLUI_Rollout : public GLUI_Panel
{
public:

/**
 Create a new rollout.  A rollout contains a set of controls,
 like a panel, but can be collapsed to just the name.
 
  @param parent The panel our object is inside; or the main GLUI object.
  @param name String to show at the top of the rollout.
  @param open Optional boolean.  If true (the default), the rollout's controls are displayed.
    If false, the rollout is closed to display only the name.
  @param type Optional style to display the panel with--GLUI_PANEL_EMBOSSED by default.
      GLUI_PANEL_RAISED causes the panel to appear higher than the surroundings.
      GLUI_PANEL_NONE causes the panel's outline to be invisible.
*/
    GLUI_Rollout( GLUI_Node *parent, const char *name, int open=true, 
                  int type=GLUI_PANEL_EMBOSSED );
    GLUI_Rollout( void ) { common_init(); }
    
    
    bool        currently_inside, initially_inside;
    GLUI_Button  button;

    void draw( int x, int y );
    void draw_pressed( void );
    int mouse_down_handler( int local_x, int local_y );
    int mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
        
    void  open( void ); 
    void  close( void );

    void update_size( void );

protected:
    void common_init() {
        currently_inside = false;
        initially_inside = false;
        can_activate     = true;
        is_container     = true;
        h                = GLUI_DEFAULT_CONTROL_HEIGHT + 7;
        w                = GLUI_DEFAULT_CONTROL_WIDTH;
        y_off_top        = 21;
        collapsible      = true;
        name = "";
    }
};

/************************************************************/
/*                                                          */
/*               Tree    Panel class (container)            */
/*                         JVK                              */
/************************************************************/

/**
  One collapsible entry in a GLUI_TreePanel.
*/
class GLUIAPI GLUI_Tree : public GLUI_Panel
{
public:
    GLUI_Tree(GLUI_Node *parent, const char *name, 
              int open=false, int inset=0);

private:
    int level;   // how deep is this node
    float red;   //Color coding of column line
    float green;
    float blue;
    float lred;   //Color coding of level name
    float lgreen;
    float lblue;
    int id;
    GLUI_Column *column;
    int is_current;          // Whether this tree is the
    // current root in a treePanel
    int child_number;
    int format;

public:
    bool        currently_inside, initially_inside;
    GLUI_Button  button;
    GLUI_String  level_name; // level name, eg: 1.1.2, III, or 3
    GLUI_TreePanel *panel; 

    void draw( int x, int y );
    void draw_pressed( void );
    int mouse_down_handler( int local_x, int local_y );
    int mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    void set_column(GLUI_Column *c) { column = c; }
    void  open( void ); 
    void  close( void );

    /*   void set_name( const char *text )   { panel.set_name( text ); }; */
    void update_size( void );
    void set_id(int i) { id = i; }
    void set_level(int l) { level = l; }
    void set_format(int f) { format = f; }
    void set_current(int c) { is_current = c; }
    int get_id() { return id; }
    int get_level() { return level; }
    int get_child_number() { return child_number; }
    void enable_bar() { if (column) { column->int_val = 1;  set_color(red, green, blue); } }
    void disable_bar() { if (column) { column->int_val = 0;  } } 
    void set_child_number(int c) { child_number = c; } 
    void set_level_color(float r, float g, float b) { 
        lred = r;
        lgreen = g;
        lblue  = b;
    }
    void set_color(float r, float g, float b) { 
        red = r;
        green = g;
        blue  = b;
    }
protected:
    void common_init()
    {
        currently_inside = false;
        initially_inside = false;
        can_activate     = true;
        is_container     = true;
        h                = GLUI_DEFAULT_CONTROL_HEIGHT + 7;
        w                = GLUI_DEFAULT_CONTROL_WIDTH;
        y_off_top        = 21;
        collapsible      = true;
        red              = .5;
        green            = .5;
        blue             = .5;
        lred             = 0;
        lgreen           = 0;
        lblue            = 0;
        column           = NULL;
        is_current       = 0;
        child_number     = 0;
        format           = 0;
        panel            = NULL;
        name             = "";
        level_name       = "";
        level            = 0;
    
    };
};


/************************************************************/
/*                                                          */
/*               TreePanel class (container) JVK            */
/*                                                          */
/************************************************************/

/**
  Manages, maintains, and formats a tree of GLUI_Tree objects.
  These are shown in a heirarchical, collapsible display.
  
  FIXME: There's an infinite loop in the traversal code (OSL 2006/06)
*/
class GLUIAPI GLUI_TreePanel : public GLUI_Panel 
{
public:
    GLUI_TreePanel(GLUI_Node *parent, const char *name,
                   bool open=false, int inset=0);

    int max_levels;
    int next_id;
    int format;
    float red;
    float green;
    float blue;
    float lred;
    float lgreen;
    float lblue;
    int root_children;
    /* These variables allow the tree panel to traverse the tree
       using only two function calls. (Well, four, if you count 
       going in reverse */

    GLUI_Tree    *curr_branch; /* Current Branch */
    GLUI_Panel *curr_root;   /* Current Root */

public:
    void            set_color(float r, float g, float b); 
    void            set_level_color(float r, float g, float b);
    void            set_format(int f) { format = f; }

    /* Adds branch to curr_root */
    GLUI_Tree *     ab(const char *name, GLUI_Tree *root = NULL);
    /* Goes up one level, resets curr_root and curr_branch to parents*/
    void            fb(GLUI_Tree *branch= NULL);
    /* Deletes the curr_branch, goes up one level using fb */
    void            db(GLUI_Tree *branch = NULL);
    /* Finds the very last branch of curr_root, resets vars */
    void            descendBranch(GLUI_Panel *root = NULL);
    /* Resets curr_root and curr branch to TreePanel and lastChild */
    void            resetToRoot(GLUI_Panel *new_root = NULL);
    void            next( void );
    void            refresh( void );
    void            expand_all( void );
    void            collapse_all( void );
    void            update_all( void );
    void            initNode(GLUI_Tree *temp);
    void            formatNode(GLUI_Tree *temp);

protected:
    int uniqueID( void ) { next_id++; return next_id - 1; }
    void common_init() 
    {
        GLUI_Panel();
        next_id = 0;
        curr_root = this;
        curr_branch = NULL;
        red = .5;
        green = .5;
        blue = .5;
        root_children = 0;
    }
};

/************************************************************/
/*                                                          */
/*                     User-Level GLUI class                */
/*                                                          */
/************************************************************/

class GLUI_Rotation;
class GLUI_Translation;

/**
 The main user-visible interface object to GLUI.
 
*/
class GLUIAPI GLUI : public GLUI_Main 
{
public:
/** DEPRECATED interface for creating new GLUI objects */
    int   add_control( GLUI_Control *control ) { return main_panel->add_control(control); }

    void  add_column( int draw_bar = true );
    void  add_column_to_panel( GLUI_Panel *panel, int draw_bar = true );

    void  add_separator( void );
    void  add_separator_to_panel( GLUI_Panel *panel );

    GLUI_RadioGroup 
    *add_radiogroup( int *live_var=NULL,
                     int user_id=-1,GLUI_CB callback=GLUI_CB());

    GLUI_RadioGroup 
    *add_radiogroup_to_panel(  GLUI_Panel *panel,
                               int *live_var=NULL,
                               int user_id=-1, GLUI_CB callback=GLUI_CB() );
    GLUI_RadioButton
    *add_radiobutton_to_group(  GLUI_RadioGroup *group,
                                const char *name );

    GLUI_Listbox *add_listbox( const char *name, int *live_var=NULL,
                               int id=-1, GLUI_CB callback=GLUI_CB()	);
    GLUI_Listbox *add_listbox_to_panel( GLUI_Panel *panel,
                                        const char *name, int *live_var=NULL,
                                        int id=-1, GLUI_CB callback=GLUI_CB());

    GLUI_Rotation *add_rotation( const char *name, float *live_var=NULL,
                                 int id=-1, GLUI_CB callback=GLUI_CB()	);
    GLUI_Rotation *add_rotation_to_panel( GLUI_Panel *panel,
                                          const char *name, float *live_var=NULL,
                                          int id=-1, GLUI_CB callback=GLUI_CB());
  
    GLUI_Translation *add_translation( const char *name,
                                       int trans_type, float *live_var=NULL,
                                       int id=-1, GLUI_CB callback=GLUI_CB()	);
    GLUI_Translation *add_translation_to_panel( 
        GLUI_Panel *panel, const char *name, 
        int trans_type, float *live_var=NULL,
        int id=-1, GLUI_CB callback=GLUI_CB());
  
    GLUI_Checkbox  *add_checkbox( const char *name, 
                                  int *live_var=NULL,
                                  int id=-1, GLUI_CB callback=GLUI_CB());
    GLUI_Checkbox  *add_checkbox_to_panel( GLUI_Panel *panel, const char *name, 
                                           int *live_var=NULL, int id=-1, 
                                           GLUI_CB callback=GLUI_CB());

    GLUI_Button  *add_button( const char *name, int id=-1, 
                              GLUI_CB callback=GLUI_CB());
    GLUI_Button  *add_button_to_panel( GLUI_Panel *panel, const char *name, 
                                       int id=-1, GLUI_CB callback=GLUI_CB() );

    GLUI_StaticText  *add_statictext( const char *name );
    GLUI_StaticText  *add_statictext_to_panel( GLUI_Panel *panel, const char *name );

    GLUI_EditText  *add_edittext( const char *name, 
                                  int data_type=GLUI_EDITTEXT_TEXT,
                                  void*live_var=NULL,
                                  int id=-1, GLUI_CB callback=GLUI_CB()	);
    GLUI_EditText  *add_edittext_to_panel( GLUI_Panel *panel, 
                                           const char *name,
                                           int data_type=GLUI_EDITTEXT_TEXT,
                                           void *live_var=NULL, int id=-1, 
                                           GLUI_CB callback=GLUI_CB() );
    GLUI_EditText  *add_edittext( const char *name, GLUI_String& live_var, 
                                  int id=-1, GLUI_CB callback=GLUI_CB()	);
    GLUI_EditText  *add_edittext_to_panel( GLUI_Panel *panel, const char *name, 
                                           GLUI_String& live_var, int id=-1,
                                           GLUI_CB callback=GLUI_CB() );

    GLUI_Spinner  *add_spinner( const char *name, 
                                int data_type=GLUI_SPINNER_INT,
                                void *live_var=NULL,
                                int id=-1, GLUI_CB callback=GLUI_CB() );
    GLUI_Spinner  *add_spinner_to_panel( GLUI_Panel *panel, 
                                         const char *name,
                                         int data_type=GLUI_SPINNER_INT,
                                         void *live_var=NULL,
                                         int id=-1,
                                         GLUI_CB callback=GLUI_CB() );

    GLUI_Panel     *add_panel( const char *name, int type=GLUI_PANEL_EMBOSSED );
    GLUI_Panel     *add_panel_to_panel( GLUI_Panel *panel, const char *name, 
                                        int type=GLUI_PANEL_EMBOSSED );


    GLUI_Rollout   *add_rollout( const char *name, int open=true,
                                 int type=GLUI_PANEL_EMBOSSED);
    GLUI_Rollout   *add_rollout_to_panel( GLUI_Panel *panel, const char *name, 
                                          int open=true,
                                          int type=GLUI_PANEL_EMBOSSED);


/** Set the window where our widgets should be displayed. */
    void            set_main_gfx_window( int window_id );
    int             get_glut_window_id( void ) { return glut_window_id; }

    void            enable( void ) { main_panel->enable(); }
    void            disable( void );

    void            sync_live( void );

    void            close( void );

    void            show( void );
    void            hide( void );

    /***** GLUT callback setup functions *****/
    /*
      void set_glutDisplayFunc(void (*f)(void));
      void set_glutReshapeFunc(void (*f)(int width, int height));
      void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y));
      void set_glutSpecialFunc(void (*f)(int key, int x, int y));
      void set_glutMouseFunc(void (*f)(int button, int state, int x, int y));
      void set_glutMotionFunc(void (*f)(int x, int y));
      void set_glutPassiveMotionFunc(void (*f)(int x, int y));
      void set_glutEntryFunc(void (*f)(int state));
      void set_glutVisibilityFunc(void (*f)(int state));
      void set_glutInit( int *argcp, const char **argv );
      void set_glutInitWindowSize(int width, int height);
      void set_glutInitWindowPosition(int x, int y);
      void set_glutInitDisplayMode(unsigned int mode);
      int  set_glutCreateWindow(const char *name);
    */

    /***** Constructors and desctructors *****/

    int init( const char *name, long flags, int x, int y, int parent_window );
protected:
    virtual int add_control( GLUI_Node *parent, GLUI_Control *control ) {
        return GLUI_Main::add_control( parent, control );
    }
};

/************************************************************/
/*                                                          */
/*               EditText class                             */
/*                                                          */
/************************************************************/

class GLUIAPI GLUI_EditText : public GLUI_Control
{
public:
    int                 has_limits;
    int                 data_type;
    GLUI_String         orig_text;
    int                 insertion_pt;
    int                 title_x_offset;
    int                 text_x_offset;
    int                 substring_start; /*substring that gets displayed in box*/
    int                 substring_end;  
    int                 sel_start, sel_end;  /* current selection */
    int                 num_periods;
    int                 last_insertion_pt;
    float               float_low, float_high;
    int                 int_low, int_high;
    GLUI_Spinner       *spinner;
    int                 debug;
    int                 draw_text_only;


    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  key_handler( unsigned char key,int modifiers );
    int  special_handler( int key, int modifiers );

    void activate( int how );
    void deactivate( void );

    void draw( int x, int y );

    int  mouse_over( int state, int x, int y );

    int  find_word_break( int start, int direction );
    int  substring_width( int start, int end );
    void clear_substring( int start, int end );
    int  find_insertion_pt( int x, int y );
    int  update_substring_bounds( void );
    void update_and_draw_text( void );
    void draw_text( int x, int y );
    void draw_insertion_pt( void );
    void set_numeric_text( void );
    void update_x_offsets( void );
    void update_size( void );

    void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP);
    void set_int_limits( int low, int high, int limit_type=GLUI_LIMIT_CLAMP );
    void set_float_val( float new_val );
    void set_int_val( int new_val );
    void set_text( const char *text );
    void set_text( const GLUI_String &s) { set_text(s.c_str()); }
    const char *get_text()               { return text.c_str(); }

    void dump( FILE *out, const char *text );

    // Constructor, no live variable
    GLUI_EditText( GLUI_Node *parent, const char *name,
                   int text_type=GLUI_EDITTEXT_TEXT,
                   int id=-1, GLUI_CB callback=GLUI_CB() );
    // Constructor, int live variable
    GLUI_EditText( GLUI_Node *parent, const char *name,
                   int *live_var,
                   int id=-1, GLUI_CB callback=GLUI_CB() );
    // Constructor, float live variable
    GLUI_EditText( GLUI_Node *parent, const char *name,
                   float *live_var,
                   int id=-1, GLUI_CB callback=GLUI_CB() );
    // Constructor, char* live variable
    GLUI_EditText( GLUI_Node *parent, const char *name, 
                   char *live_var,
                   int id=-1, GLUI_CB callback=GLUI_CB() );
    // Constructor, std::string live variable
    GLUI_EditText( GLUI_Node *parent, const char *name, 
                   std::string &live_var,
                   int id=-1, GLUI_CB callback=GLUI_CB() );

    // Deprecated constructor, only called internally
    GLUI_EditText( GLUI_Node *parent, const char *name,
                   int text_type, void *live_var,
                   int id, GLUI_CB callback );
    // Deprecated constructor, only called internally
    GLUI_EditText( void ) { common_init(); }

protected:
    void common_init( void ) {
        h                     = GLUI_EDITTEXT_HEIGHT;
        w                     = GLUI_EDITTEXT_WIDTH;
        title_x_offset        = 0;
        text_x_offset         = 55;
        insertion_pt          = -1;
        last_insertion_pt     = -1;
        name                  = "";
        substring_start       = 0;
        data_type             = GLUI_EDITTEXT_TEXT;
        substring_end         = 2;
        num_periods           = 0;
        has_limits            = GLUI_LIMIT_NONE;
        sel_start             = 0;
        sel_end               = 0;
        active_type           = GLUI_CONTROL_ACTIVE_PERMANENT;
        can_activate          = true;
        spacebar_mouse_click  = false;
        spinner               = NULL;
        debug                 = false;
        draw_text_only        = false;
    }
    void common_construct( GLUI_Node *parent, const char *name, 
                           int data_type, int live_type, void *live_var,
                           int id, GLUI_CB callback );
};

/************************************************************/
/*                                                          */
/*               CommandLine class                          */
/*                                                          */
/************************************************************/

//moved here to make it compile in VS2010(can only do this in namespace scope).
#ifdef _MSC_VER
// Explicit template instantiation needed for dll
template class GLUIAPI std::allocator<GLUI_String>;
template class GLUIAPI std::vector<GLUI_String, std::allocator<GLUI_String> >;
#endif

class GLUIAPI GLUI_CommandLine : public GLUI_EditText
{
public:
    typedef GLUI_EditText Super;

    enum { HIST_SIZE = 100 };   

    std::vector<GLUI_String> hist_list;
    int  curr_hist;
    int  oldest_hist;
    int  newest_hist;
    bool commit_flag;

public:
    int  key_handler( unsigned char key,int modifiers );
    int  special_handler(	int key,int modifiers );
    void deactivate( void );

    virtual const char *get_history( int command_number ) const
    { return hist_list[command_number - oldest_hist].c_str(); }
    virtual GLUI_String& get_history_str( int command_number )
    { return hist_list[command_number - oldest_hist]; }
    virtual const GLUI_String& get_history_str( int command_number ) const
    { return hist_list[command_number - oldest_hist]; }
    virtual void recall_history( int history_number );
    virtual void scroll_history( int direction );
    virtual void add_to_history( const char *text );
    virtual void reset_history( void );

    void dump( FILE *out, const char *text );


    GLUI_CommandLine( GLUI_Node *parent, const char *name, void *live_var=NULL,
                      int id=-1, GLUI_CB callback=GLUI_CB() );
    GLUI_CommandLine( void ) { common_init(); }
protected:
    void common_init() {
        hist_list.resize(HIST_SIZE);
        curr_hist = 0;
        oldest_hist = 0;
        newest_hist = 0;
        commit_flag = false;
    }

};

/************************************************************/
/*                                                          */
/*              RadioGroup class (container)                */
/*                                                          */
/************************************************************/

class GLUIAPI GLUI_RadioGroup : public GLUI_Control
{
public:
    int  num_buttons;

    void draw( int x, int y );
    void set_name( const char *text );
    void set_int_val( int int_val ); 
    void set_selected( int int_val );

    void draw_group( int translate );

    GLUI_RadioGroup( GLUI_Node *parent, int *live_var=NULL,
                     int user_id=-1,GLUI_CB callback=GLUI_CB() );
    GLUI_RadioGroup( void ) { common_init(); }

protected:
    void common_init( void ) {
        x_off         = 0;
        y_off_top     = 0;
        y_off_bot     = 0;
        is_container  = true;
        w             = 300;
        h             = 300;
        num_buttons   = 0;
        name          = "";
        can_activate  = false;
        live_type     = GLUI_LIVE_INT;
    }
};

/************************************************************/
/*                                                          */
/*               RadioButton class (container)              */
/*                                                          */
/************************************************************/

class GLUIAPI GLUI_RadioButton : public GLUI_Control
{
public:
    int orig_value;
    bool currently_inside;
    int text_x_offset;

    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );

    void draw( int x, int y );
    void update_size( void );

    void draw_active_area( void );
    void draw_checked( void );
    void draw_unchecked( void );
    void draw_O( void );

    GLUI_RadioButton( GLUI_RadioGroup *group, const char *name );
    GLUI_RadioGroup *group;

protected:
    void common_init()
    {
        glui_format_str( name, "RadioButton: %p", (void *) this );
        h              = GLUI_RADIOBUTTON_SIZE;
        group          = NULL;
        orig_value     = -1;
        text_x_offset  = 18;
        can_activate   = true;
    }
};


/************************************************************/
/*                                                          */
/*               Separator class (container)                */
/*                                                          */
/************************************************************/

class GLUIAPI GLUI_Separator : public GLUI_Control
{
public:
    void draw( int x, int y );

    GLUI_Separator( GLUI_Node *parent );
    GLUI_Separator( void ) { common_init(); }

protected:
    void common_init() {
        w            = 100;
        h            = GLUI_SEPARATOR_HEIGHT;
        can_activate = false;
    }
};

#define  GLUI_SPINNER_ARROW_WIDTH   12
#define  GLUI_SPINNER_ARROW_HEIGHT   8
#define  GLUI_SPINNER_ARROW_Y        2

#define  GLUI_SPINNER_STATE_NONE     0
#define  GLUI_SPINNER_STATE_UP       1
#define  GLUI_SPINNER_STATE_DOWN     2
#define  GLUI_SPINNER_STATE_BOTH     3

#define  GLUI_SPINNER_DEFAULT_GROWTH_EXP   1.05f

/************************************************************/
/*                                                          */
/*               Spinner class (container)                  */
/*                                                          */
/************************************************************/
 
class GLUIAPI GLUI_Spinner : public GLUI_Control
{
public:
    // Constructor, no live var
    GLUI_Spinner( GLUI_Node* parent, const char *name, 
                  int data_type=GLUI_SPINNER_INT, int id=-1, GLUI_CB callback=GLUI_CB() );
    // Constructor, int live var
    GLUI_Spinner( GLUI_Node* parent, const char *name, 
                  int *live_var, int id=-1, GLUI_CB callback=GLUI_CB() );
    // Constructor, float live var
    GLUI_Spinner( GLUI_Node* parent, const char *name, 
                  float *live_var, int id=-1, GLUI_CB callback=GLUI_CB() );
    // Deprecated constructor
    GLUI_Spinner( GLUI_Node* parent, const char *name, 
                  int data_type,
                  void *live_var,
                  int id=-1, GLUI_CB callback=GLUI_CB() );
    // Deprecated constructor
    GLUI_Spinner( void ) { common_init(); }

    bool          currently_inside;
    int           state;
    float         growth, growth_exp;
    int           last_x, last_y;
    int           data_type;
    int           callback_count;
    int           last_int_val;
    float         last_float_val;
    int           first_callback;
    float         user_speed;

    GLUI_EditText *edittext;

    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  key_handler( unsigned char key,int modifiers );
    int  special_handler(   int key,int modifiers );

    void draw( int x, int y );
    void draw_pressed( void );
    void draw_unpressed( void );
    void draw_text( int sunken );

    void update_size( void );

    void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP);
    void set_int_limits( int low, int high,int limit_type=GLUI_LIMIT_CLAMP);
    int  find_arrow( int local_x, int local_y );
    void do_drag( int x, int y );
    void do_callbacks( void );
    void do_click( void );
    void idle( void );
    bool needs_idle( void ) const;

    const char *get_text( void );

    void set_float_val( float new_val );
    void set_int_val( int new_val );
    float  get_float_val( void );
    int    get_int_val( void );
    void increase_growth( void );
    void reset_growth( void );

    void set_speed( float speed ) { user_speed = speed; }

protected:
    void common_init() {
        glui_format_str( name, "Spinner: %p", this );
        h            = GLUI_EDITTEXT_HEIGHT;
        w            = GLUI_EDITTEXT_WIDTH;
        x_off        = 0;
        y_off_top    = 0;
        y_off_bot    = 0;
        can_activate = true;
        state        = GLUI_SPINNER_STATE_NONE;
        edittext     = NULL;
        growth_exp   = GLUI_SPINNER_DEFAULT_GROWTH_EXP;
        callback_count = 0;
        first_callback = true;
        user_speed   = 1.0;
    }
    void common_construct( GLUI_Node* parent, const char *name, 
                           int data_type, void *live_var,
                           int id, GLUI_CB callback );
};

/************************************************************/
/*                                                          */
/*               StaticText class                           */
/*                                                          */
/************************************************************/

class GLUIAPI GLUI_StaticText : public GLUI_Control
{
public:
    void set_text( const char *text );
    void draw( int x, int y );
    void draw_text( void );
    void update_size( void );
    void erase_text( void );

    GLUI_StaticText(GLUI_Node *parent, const char *name);
    GLUI_StaticText( void ) { common_init(); }

protected:
    void common_init() {
        h       = GLUI_STATICTEXT_SIZE;
        name    = "";
        can_activate  = false;
    }
};

/************************************************************/
/*                                                          */
/*               TextBox class - JVK                        */
/*                                                          */
/************************************************************/

class GLUIAPI GLUI_TextBox : public GLUI_Control
{
public:
    /* GLUI Textbox - JVK */
    GLUI_TextBox(GLUI_Node *parent, GLUI_String &live_var,
                 bool scroll = false, int id=-1, GLUI_CB callback=GLUI_CB() );
    GLUI_TextBox( GLUI_Node *parent,
                  bool scroll = false, int id=-1,
                  GLUI_CB callback=GLUI_CB() );

    GLUI_String         orig_text;
    int                 insertion_pt;
    int                 substring_start; /*substring that gets displayed in box*/
    int                 substring_end;  
    int                 sel_start, sel_end;  /* current selection */
    int                 last_insertion_pt;
    int                 debug;
    int                 draw_text_only;
    int                 tab_width;
    int                 start_line;
    int                 num_lines;
    int                 curr_line;
    int                 visible_lines;
    int                 insert_x;        /* Similar to "insertion_pt", these variables keep */
    int                 insert_y;        /* track of where the ptr is, but in pixels */
    int                 keygoal_x;       /* where up down keys would like to put insertion pt*/
    GLUI_Scrollbar     *scrollbar;
    // EG: Added
    bool                continuous_callback;

    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  key_handler( unsigned char key,int modifiers );
    int  special_handler( int key,int modifiers );
  
    void activate( int how );
    void deactivate( void );

    void enable( void );
    void disable( void );

    void draw( int x, int y );

    int  mouse_over( int state, int x, int y );

    int get_box_width();
    int  find_word_break( int start, int direction );
    int  substring_width( int start, int end, int initial_width=0 );
    void clear_substring( int start, int end );
    int  find_insertion_pt( int x, int y );
    int  update_substring_bounds( void );
    void update_and_draw_text( void );
    void draw_text( int x, int y );
    void draw_insertion_pt( void );
    void update_x_offsets( void );
    void update_size( void );

    void set_text( const char *text );
    const char *get_text( void )         { return text.c_str(); }

    void dump( FILE *out, char *text );
    void set_tab_w(int w) { tab_width = w; }
    void set_start_line(int l) { start_line = l; }
    static void scrollbar_callback(GLUI_Control*);

    bool wants_tabs( void ) const { return true; }

protected:
    void common_init()
    {
        h                     = GLUI_TEXTBOX_HEIGHT;
        w                     = GLUI_TEXTBOX_WIDTH;
        tab_width             = GLUI_TAB_WIDTH;
        num_lines             = 0;
        visible_lines         = 0;
        start_line            = 0;
        curr_line             = 0;
        insert_y              = -1;
        insert_x              = -1;
        insertion_pt          = -1;
        last_insertion_pt     = -1;
        name[0]               = '\0';
        substring_start       = 0;
        substring_end         = 2;
        sel_start             = 0;
        sel_end               = 0;
        active_type           = GLUI_CONTROL_ACTIVE_PERMANENT;
        can_activate          = true;
        spacebar_mouse_click  = false;
        scrollbar             = NULL;
        debug                 = false;
        draw_text_only        = false;
    }
    void common_construct(
        GLUI_Node *parent, GLUI_String *live_var, 
        bool scroll, int id, GLUI_CB callback); 
};

/************************************************************/
/*                                                          */
/*                   List class - JVK                       */
/*                                                          */
/************************************************************/

class GLUIAPI GLUI_List_Item : public GLUI_Node 
{
public:
    GLUI_String text;
    int         id;
};

/************************************************************/
/*                                                          */
/*               List class - JVK                           */
/*                                                          */
/************************************************************/

class GLUIAPI GLUI_List : public GLUI_Control
{
public:
    /* GLUI List - JVK */
    GLUI_List( GLUI_Node *parent, bool scroll = false,
               int id=-1, GLUI_CB callback=GLUI_CB() );
               /*, GLUI_Control *object = NULL 
               ,GLUI_InterObject_CB obj_cb = NULL);*/

    GLUI_List( GLUI_Node *parent,
               GLUI_String& live_var, bool scroll = false, 
               int id=-1, 
               GLUI_CB callback=GLUI_CB()
               /*,GLUI_Control *object = NULL */
               /*,GLUI_InterObject_CB obj_cb = NULL*/);


    GLUI_String         orig_text;
    int                 debug;
    int                 draw_text_only;
    int                 start_line;
    int                 num_lines;
    int                 curr_line;
    int                 visible_lines;
    GLUI_Scrollbar      *scrollbar;
    GLUI_List_Item      items_list;
    GLUI_Control        *associated_object;
    GLUI_CB             obj_cb;
    int                 cb_click_type;
    int                 last_line;
    int                 last_click_time;

    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  key_handler( unsigned char key,int modifiers );
    int  special_handler( int key,int modifiers );
  
    void activate( int how );
    void deactivate( void );

    void draw( int x, int y );

    int  mouse_over( int state, int x, int y );

    int get_box_width();
    int  find_word_break( int start, int direction );
    int  substring_width( const char *t, int start, int end );
    int  find_line( int x, int y );
    void update_and_draw_text( void );
    void draw_text( const char *t, int selected, int x, int y );
    void update_size( void );


    int  add_item( int id, const char *text );
    int  delete_item( const char *text );
    int  delete_item( int id );
    int  delete_all();

    GLUI_List_Item *get_item_ptr( const char *text );
    GLUI_List_Item *get_item_ptr( int id );

    void dump( FILE *out, const char *text );
    void set_start_line(int l) { start_line = l; }
    static void scrollbar_callback(GLUI_Control*);
    int get_current_item() { return curr_line; }
    void set_click_type(int d) {
        cb_click_type = d; }
    void set_object_callback(GLUI_CB cb=GLUI_CB(), GLUI_Control*obj=NULL)
    { obj_cb=cb; associated_object=obj; }

protected:
    void common_init()
    {
        h                     = GLUI_LIST_HEIGHT;
        w                     = GLUI_LIST_WIDTH;
        num_lines             = 0;
        visible_lines         = 0;
        start_line            = 0;
        curr_line             = 0;
        name[0]               = '\0';
        active_type           = GLUI_CONTROL_ACTIVE_PERMANENT;
        can_activate          = true;
        spacebar_mouse_click  = false;
        scrollbar             = NULL;
        debug                 = false;
        draw_text_only        = false;
        cb_click_type         = GLUI_SINGLE_CLICK;
        last_line             = -1;
        last_click_time       = 0;
        associated_object     = NULL;
    };
    void common_construct(
        GLUI_Node *parent,
        GLUI_String* live_var, bool scroll,
        int id,
        GLUI_CB callback
        /*,GLUI_Control *object*/
        /*,GLUI_InterObject_CB obj_cb*/);
};

/************************************************************/
/*                                                          */
/*               Scrollbar class - JVK                      */
/*                                                          */
/************************************************************/
 
class GLUIAPI GLUI_Scrollbar : public GLUI_Control
{
public:
    // Constructor, no live var
    GLUI_Scrollbar( GLUI_Node *parent,
                    const char *name, 
                    int horz_vert=GLUI_SCROLL_HORIZONTAL,
                    int data_type=GLUI_SCROLL_INT,
                    int id=-1, GLUI_CB callback=GLUI_CB() 
                    /*,GLUI_Control *object = NULL*/
                    /*,GLUI_InterObject_CB obj_cb = NULL*/
                    );

    // Constructor, int live var
    GLUI_Scrollbar( GLUI_Node *parent, const char *name, int horz_vert,
                    int *live_var,
                    int id=-1, GLUI_CB callback=GLUI_CB() 
                    /*,GLUI_Control *object = NULL*/
                    /*,GLUI_InterObject_CB obj_cb = NULL*/
                    );

    // Constructor, float live var
    GLUI_Scrollbar( GLUI_Node *parent, const char *name, int horz_vert,
                    float *live_var,
                    int id=-1, GLUI_CB callback=GLUI_CB()
                    /*,GLUI_Control *object = NULL*/
                    /*,GLUI_InterObject_CB obj_cb = NULL*/
                    );

    bool          currently_inside;
    int           state;
    float         growth, growth_exp;
    int           last_x, last_y;
    int           data_type;
    int           callback_count;
    int           last_int_val;  ///< Used to prevent repeated callbacks.
    float         last_float_val;
    int           first_callback;
    float         user_speed;
    float         float_min, float_max;
    int           int_min, int_max;
    int           horizontal;
    double     last_update_time; ///< GLUI_Time() we last advanced scrollbar.
    double     velocity_limit; ///< Maximum distance to advance per second.
    int box_length;
    int box_start_position;
    int box_end_position;
    int track_length;


    /* Rather than directly access an Editbox or Textbox for 
       changing variables, a pointer to some object is defined
       along with a static callback in the form func(void *, int) -
       the int is the new value, the void * must be cast to that
       particular object type before use.
    */
    void *        associated_object; /* Lets the Spinner manage it's own callbacks */
    GLUI_CB       object_cb; /* function pointer to object call_back */

    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  key_handler( unsigned char key,int modifiers );
    int  special_handler( int key,int modifiers );
  
    void draw( int x, int y );
    void draw_pressed( void );
    void draw_unpressed( void );
    void draw_text( int sunken );

    void update_size( void );

    void set_int_limits( int low, int high,int limit_type=GLUI_LIMIT_CLAMP);
    void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP);
    int  find_arrow( int local_x, int local_y );
    void do_drag( int x, int y );
    void do_callbacks( void );
    void draw_scroll( void );
    void do_click( void );
    void idle( void );
    bool needs_idle( void ) const;
    void set_int_val( int new_val );
    void set_float_val( float new_val );
    void increase_growth( void );
    void reset_growth( void );

    void set_speed( float speed ) { user_speed = speed; };
    void update_scroll_parameters();
    void set_object_callback(GLUI_CB cb=GLUI_CB(), GLUI_Control*obj=NULL)
    { object_cb=cb; associated_object=obj; }

protected:
    void common_init ( void );
    void common_construct(
        GLUI_Node *parent,
        const char *name, 
        int horz_vert,
        int data_type, void* live_var,
        int id, GLUI_CB callback
        /*,GLUI_Control *object
        ,GLUI_InterObject_CB obj_cb*/
        );

    virtual void draw_scroll_arrow(int arrowtype, int x, int y);
    virtual void draw_scroll_box(int x, int y, int w, int h);
};

/************************************************************/
/*                                                          */
/*                   Listbox class                          */
/*                                                          */
/************************************************************/

class GLUIAPI GLUI_Listbox_Item : public GLUI_Node 
{
public:
    GLUI_String text;
    int         id;
};

class GLUIAPI GLUI_Listbox : public GLUI_Control
{
public:
    GLUI_String       curr_text;
    GLUI_Listbox_Item items_list;
    int               depressed;

    int  orig_value;
    bool currently_inside;
    int  text_x_offset, title_x_offset;
    int  glut_menu_id;

    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  key_handler( unsigned char key,int modifiers );
    int  special_handler( int key,int modifiers );

    void update_size( void );
    void draw( int x, int y );
    int  mouse_over( int state, int x, int y );

    void set_int_val( int new_val );
    void dump( FILE *output );

    int  add_item( int id, const char *text );
    int  delete_item( const char *text );
    int  delete_item( int id );
    int  sort_items( void );

    int  do_selection( int item );

    GLUI_Listbox_Item *get_item_ptr( const char *text );
    GLUI_Listbox_Item *get_item_ptr( int id );
  

    GLUI_Listbox( GLUI_Node *parent,
                  const char *name, int *live_var=NULL,
                  int id=-1, GLUI_CB callback=GLUI_CB() );
    GLUI_Listbox( void ) { common_init(); }

protected:
    /** Change w and return true if we need to be widened to fit the current item. */
    bool recalculate_item_width( void );
    void common_init() {
        glui_format_str( name, "Listbox: %p", this );
        w              = GLUI_EDITTEXT_WIDTH;
        h              = GLUI_EDITTEXT_HEIGHT;
        orig_value     = -1;
        title_x_offset = 0;
        text_x_offset  = 55;
        can_activate   = true;
        curr_text      = "";
        live_type      = GLUI_LIVE_INT;  /* This has an integer live var */
        depressed      = false;
        glut_menu_id   = -1;
    }

    ~GLUI_Listbox();
};

/************************************************************/
/*                                                          */
/*              Mouse_Interaction class                     */
/*                                                          */
/************************************************************/

/**
  This is the superclass of translation and rotation widgets.
*/
class GLUIAPI GLUI_Mouse_Interaction : public GLUI_Control
{
public:
    /*int  get_main_area_size( void ) { return MIN( h-18,  */
    int            draw_active_area_only;

    int  mouse_down_handler( int local_x, int local_y );
    int  mouse_up_handler( int local_x, int local_y, bool inside );
    int  mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  special_handler( int key, int modifiers );
    void update_size( void );
    void draw( int x, int y );
    void draw_active_area( void );

    /***  The following methods (starting with "iaction_") need to
          be overloaded  ***/
    virtual int  iaction_mouse_down_handler( int local_x, int local_y ) = 0;
    virtual int  iaction_mouse_up_handler( int local_x, int local_y, bool inside )=0;
    virtual int  iaction_mouse_held_down_handler( int local_x, int local_y, bool inside )=0;
    virtual int  iaction_special_handler( int key, int modifiers )=0;
    virtual void iaction_draw_active_area_persp( void )=0;
    virtual void iaction_draw_active_area_ortho( void )=0;
    virtual void iaction_dump( FILE *output )=0;
    virtual void iaction_init( void ) = 0;
  
    GLUI_Mouse_Interaction( void ) {
        glui_format_str( name, "Mouse_Interaction: %p", this );
        w              = GLUI_MOUSE_INTERACTION_WIDTH;
        h              = GLUI_MOUSE_INTERACTION_HEIGHT;
        can_activate   = true;
        live_type      = GLUI_LIVE_NONE;
        alignment      = GLUI_ALIGN_CENTER;
        draw_active_area_only = false;
    }
};

/************************************************************/
/*                                                          */
/*                   Rotation class                         */
/*                                                          */
/************************************************************/

/**
  An onscreen rotation controller--allows the user to interact with
  a 3D rotation via a spaceball-like interface.
*/
class GLUIAPI GLUI_Rotation : public GLUI_Mouse_Interaction
{
public:
    Arcball        *ball;
    GLUquadricObj *quadObj;
    bool           can_spin, spinning;
    float          damping;
  
    int  iaction_mouse_down_handler( int local_x, int local_y );
    int  iaction_mouse_up_handler( int local_x, int local_y, bool inside );
    int  iaction_mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  iaction_special_handler( int key, int modifiers );
    void iaction_init( void ) { init_ball(); }
    void iaction_draw_active_area_persp( void );
    void iaction_draw_active_area_ortho( void );
    void iaction_dump( FILE *output );

    /*  void update_size( void ); */
    /*  void draw( int x, int y ); */
    /*  int mouse_over( int state, int x, int y ); */

    void setup_texture( void );
    void setup_lights( void );
    void draw_ball( float radius );

    void init_ball( void );

    void reset( void );

    bool needs_idle( void ) const;
    void idle( void );

    void copy_float_array_to_ball( void );
    void copy_ball_to_float_array( void );

    void set_spin( float damp_factor );

    GLUI_Rotation( GLUI_Node *parent, const char *name, float *live_var=NULL,
                   int id=-1, GLUI_CB callback=GLUI_CB() );
    GLUI_Rotation(void) { common_init(); }

protected:
    void common_init();
};

/************************************************************/
/*                                                          */
/*                   Translation class                      */
/*                                                          */
/************************************************************/

/**
  An onscreen translation controller--allows the user to interact with
  a 3D translation.
*/
class GLUIAPI GLUI_Translation : public GLUI_Mouse_Interaction
{
public:
    int trans_type;  /* Is this an XY or a Z controller? */
    int down_x, down_y;
    float scale_factor;
    GLUquadricObj *quadObj;
    int   trans_mouse_code;
    float orig_x, orig_y, orig_z;
    int   locked;

    int  iaction_mouse_down_handler( int local_x, int local_y );
    int  iaction_mouse_up_handler( int local_x, int local_y, bool inside );
    int  iaction_mouse_held_down_handler( int local_x, int local_y, bool inside );
    int  iaction_special_handler( int key, int modifiers );
    void iaction_init( void ) { }
    void iaction_draw_active_area_persp( void );
    void iaction_draw_active_area_ortho( void );
    void iaction_dump( FILE *output );

    void set_speed( float s ) { scale_factor = s; }

    void setup_texture( void );
    void setup_lights( void );
    void draw_2d_arrow( int radius, int filled, int orientation ); 
    void draw_2d_x_arrows( int radius );
    void draw_2d_y_arrows( int radius );
    void draw_2d_z_arrows( int radius );
    void draw_2d_xy_arrows( int radius );

    int  get_mouse_code( int x, int y );

    /* Float array is either a single float (for single-axis controls),
       or two floats for X and Y (if an XY controller) */

    float get_z( void ) {       return float_array_val[0];  }
    float get_x( void ) {       return float_array_val[0];  }
    float get_y( void ) {
        if ( trans_type == GLUI_TRANSLATION_XY )    return float_array_val[1];
        else					return float_array_val[0];
    }

    void  set_z( float val );
    void  set_x( float val );
    void  set_y( float val );
    void  set_one_val( float val, int index );

    GLUI_Translation( GLUI_Node *parent, const char *name,
                      int trans_type, float *live_var=NULL,
                      int id=-1, GLUI_CB callback=GLUI_CB()	);
    GLUI_Translation( void ) { common_init(); }

protected:
    void common_init() {
        locked              = GLUI_TRANSLATION_LOCK_NONE;
        glui_format_str( name, "Translation: %p", this );
        w                   = GLUI_MOUSE_INTERACTION_WIDTH;
        h                   = GLUI_MOUSE_INTERACTION_HEIGHT;
        can_activate        = true;
        live_type           = GLUI_LIVE_FLOAT_ARRAY;
        float_array_size    = 0;
        alignment           = GLUI_ALIGN_CENTER;
        trans_type          = GLUI_TRANSLATION_XY;
        scale_factor        = 1.0;
        quadObj             = NULL;
        trans_mouse_code    = GLUI_TRANSLATION_MOUSE_NONE;
    }
};

/********** Misc functions *********************/
int _glutBitmapWidthString( void *font, const char *s );
void _glutBitmapString( void *font, const char *s );

/********** Our own callbacks for glut *********/
/* These are the callbacks that we pass to glut.  They take
   some action if necessary, then (possibly) call the user-level
   glut callbacks.  
*/

void glui_display_func( void );
void glui_reshape_func( int w, int h );
void glui_keyboard_func(unsigned char key, int x, int y);
void glui_special_func(int key, int x, int y);
void glui_mouse_func(int button, int state, int x, int y);
void glui_motion_func(int x, int y);
void glui_passive_motion_func(int x, int y);
void glui_entry_func(int state);
void glui_visibility_func(int state);
void glui_idle_func(void);

void glui_parent_window_reshape_func( int w, int h );
void glui_parent_window_keyboard_func(unsigned char key, int x, int y);
void glui_parent_window_mouse_func(int, int, int, int );
void glui_parent_window_special_func(int key, int x, int y);

#endif