imgui_demo.cpp 291 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903
  1. // dear imgui, v1.80 WIP
  2. // (demo code)
  3. // Help:
  4. // - Read FAQ at http://dearimgui.org/faq
  5. // - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
  6. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
  7. // Read imgui.cpp for more details, documentation and comments.
  8. // Get latest version at https://github.com/ocornut/imgui
  9. // Message to the person tempted to delete this file when integrating Dear ImGui into their code base:
  10. // Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other
  11. // coders will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available
  12. // debug menu of your game/app! Removing this file from your project is hindering access to documentation for everyone
  13. // in your team, likely leading you to poorer usage of the library.
  14. // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
  15. // If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be
  16. // linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
  17. // In other situation, whenever you have Dear ImGui available you probably want this to be available for reference.
  18. // Thank you,
  19. // -Your beloved friend, imgui_demo.cpp (which you won't delete)
  20. // Message to beginner C/C++ programmers about the meaning of the 'static' keyword:
  21. // In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls,
  22. // so it is essentially like a global variable but declared inside the scope of the function. We do this as a way to
  23. // gather code and data in the same place, to make the demo source code faster to read, faster to write, and smaller
  24. // in size. It also happens to be a convenient way of storing simple UI related information as long as your function
  25. // doesn't need to be reentrant or used in multiple threads. This might be a pattern you will want to use in your code,
  26. // but most of the real data you would be editing is likely going to be stored outside your functions.
  27. // The Demo code in this file is designed to be easy to copy-and-paste in into your application!
  28. // Because of this:
  29. // - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace.
  30. // - We try to declare static variables in the local scope, as close as possible to the code using them.
  31. // - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API.
  32. // - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided
  33. // by imgui_internal.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
  34. // and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
  35. // Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
  36. /*
  37. Index of this file:
  38. // [SECTION] Forward Declarations, Helpers
  39. // [SECTION] Demo Window / ShowDemoWindow()
  40. // [SECTION] About Window / ShowAboutWindow()
  41. // [SECTION] Style Editor / ShowStyleEditor()
  42. // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
  43. // [SECTION] Example App: Debug Console / ShowExampleAppConsole()
  44. // [SECTION] Example App: Debug Log / ShowExampleAppLog()
  45. // [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
  46. // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
  47. // [SECTION] Example App: Long Text / ShowExampleAppLongText()
  48. // [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
  49. // [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
  50. // [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
  51. // [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
  52. // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
  53. // [SECTION] Example App: Docking, DockSpace / ShowExampleAppDockSpace()
  54. // [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
  55. */
  56. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
  57. #define _CRT_SECURE_NO_WARNINGS
  58. #endif
  59. #include "imgui.h"
  60. #ifndef IMGUI_DISABLE
  61. #include <ctype.h> // toupper
  62. #include <limits.h> // INT_MIN, INT_MAX
  63. #include <math.h> // sqrtf, powf, cosf, sinf, floorf, ceilf
  64. #include <stdio.h> // vsnprintf, sscanf, printf
  65. #include <stdlib.h> // NULL, malloc, free, atoi
  66. #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
  67. #include <stddef.h> // intptr_t
  68. #else
  69. #include <stdint.h> // intptr_t
  70. #endif
  71. // Visual Studio warnings
  72. #ifdef _MSC_VER
  73. #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
  74. #endif
  75. // Clang/GCC warnings with -Weverything
  76. #if defined(__clang__)
  77. #if __has_warning("-Wunknown-warning-option")
  78. #pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
  79. #endif
  80. #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
  81. #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
  82. #pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning: 'xx' is deprecated: The POSIX name for this.. // for strdup used in demo code (so user can copy & paste the code)
  83. #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type
  84. #pragma clang diagnostic ignored "-Wformat-security" // warning: format string is not a string literal
  85. #pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
  86. #pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used // we define snprintf/vsnprintf on Windows so they are available, but not always used.
  87. #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
  88. #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
  89. #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier
  90. #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
  91. #elif defined(__GNUC__)
  92. #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
  93. #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
  94. #pragma GCC diagnostic ignored "-Wformat-security" // warning: format string is not a string literal (potentially insecure)
  95. #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
  96. #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
  97. #pragma GCC diagnostic ignored "-Wmisleading-indentation" // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub.
  98. #endif
  99. // Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
  100. #ifdef _WIN32
  101. #define IM_NEWLINE "\r\n"
  102. #else
  103. #define IM_NEWLINE "\n"
  104. #endif
  105. // Helpers
  106. #if defined(_MSC_VER) && !defined(snprintf)
  107. #define snprintf _snprintf
  108. #endif
  109. #if defined(_MSC_VER) && !defined(vsnprintf)
  110. #define vsnprintf _vsnprintf
  111. #endif
  112. // Helpers macros
  113. // We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste,
  114. // but making an exception here as those are largely simplifying code...
  115. // In other imgui sources we can use nicer internal functions from imgui_internal.h (ImMin/ImMax) but not in the demo.
  116. #define IM_MIN(A, B) (((A) < (B)) ? (A) : (B))
  117. #define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B))
  118. #define IM_CLAMP(V, MN, MX) ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V))
  119. //-----------------------------------------------------------------------------
  120. // [SECTION] Forward Declarations, Helpers
  121. //-----------------------------------------------------------------------------
  122. #if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
  123. // Forward Declarations
  124. static void ShowExampleAppDockSpace(bool* p_open);
  125. static void ShowExampleAppDocuments(bool* p_open);
  126. static void ShowExampleAppMainMenuBar();
  127. static void ShowExampleAppConsole(bool* p_open);
  128. static void ShowExampleAppLog(bool* p_open);
  129. static void ShowExampleAppLayout(bool* p_open);
  130. static void ShowExampleAppPropertyEditor(bool* p_open);
  131. static void ShowExampleAppLongText(bool* p_open);
  132. static void ShowExampleAppAutoResize(bool* p_open);
  133. static void ShowExampleAppConstrainedResize(bool* p_open);
  134. static void ShowExampleAppSimpleOverlay(bool* p_open);
  135. static void ShowExampleAppWindowTitles(bool* p_open);
  136. static void ShowExampleAppCustomRendering(bool* p_open);
  137. static void ShowExampleMenuFile();
  138. // Helper to display a little (?) mark which shows a tooltip when hovered.
  139. // In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.md)
  140. static void HelpMarker(const char* desc)
  141. {
  142. ImGui::TextDisabled("(?)");
  143. if (ImGui::IsItemHovered())
  144. {
  145. ImGui::BeginTooltip();
  146. ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
  147. ImGui::TextUnformatted(desc);
  148. ImGui::PopTextWrapPos();
  149. ImGui::EndTooltip();
  150. }
  151. }
  152. static void ShowDockingDisabledMessage()
  153. {
  154. ImGuiIO& io = ImGui::GetIO();
  155. ImGui::Text("ERROR: Docking is not enabled! See Demo > Configuration.");
  156. ImGui::Text("Set io.ConfigFlags |= ImGuiConfigFlags_DockingEnable in your code, or ");
  157. ImGui::SameLine(0.0f, 0.0f);
  158. if (ImGui::SmallButton("click here"))
  159. io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
  160. }
  161. // Helper to display basic user controls.
  162. void ImGui::ShowUserGuide()
  163. {
  164. ImGuiIO& io = ImGui::GetIO();
  165. ImGui::BulletText("Double-click on title bar to collapse window.");
  166. ImGui::BulletText(
  167. "Click and drag on lower corner to resize window\n"
  168. "(double-click to auto fit window to its contents).");
  169. ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
  170. ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
  171. if (io.FontAllowUserScaling)
  172. ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
  173. ImGui::BulletText("While inputing text:\n");
  174. ImGui::Indent();
  175. ImGui::BulletText("CTRL+Left/Right to word jump.");
  176. ImGui::BulletText("CTRL+A or double-click to select all.");
  177. ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
  178. ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
  179. ImGui::BulletText("ESCAPE to revert.");
  180. ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
  181. ImGui::Unindent();
  182. ImGui::BulletText("With keyboard navigation enabled:");
  183. ImGui::Indent();
  184. ImGui::BulletText("Arrow keys to navigate.");
  185. ImGui::BulletText("Space to activate a widget.");
  186. ImGui::BulletText("Return to input text into a widget.");
  187. ImGui::BulletText("Escape to deactivate a widget, close popup, exit child window.");
  188. ImGui::BulletText("Alt to jump to the menu layer of a window.");
  189. ImGui::BulletText("CTRL+Tab to select a window.");
  190. ImGui::Unindent();
  191. }
  192. //-----------------------------------------------------------------------------
  193. // [SECTION] Demo Window / ShowDemoWindow()
  194. //-----------------------------------------------------------------------------
  195. // - ShowDemoWindowWidgets()
  196. // - ShowDemoWindowLayout()
  197. // - ShowDemoWindowPopups()
  198. // - ShowDemoWindowColumns()
  199. // - ShowDemoWindowMisc()
  200. //-----------------------------------------------------------------------------
  201. // We split the contents of the big ShowDemoWindow() function into smaller functions
  202. // (because the link time of very large functions grow non-linearly)
  203. static void ShowDemoWindowWidgets();
  204. static void ShowDemoWindowLayout();
  205. static void ShowDemoWindowPopups();
  206. static void ShowDemoWindowColumns();
  207. static void ShowDemoWindowMisc();
  208. // Demonstrate most Dear ImGui features (this is big function!)
  209. // You may execute this function to experiment with the UI and understand what it does.
  210. // You may then search for keywords in the code when you are interested by a specific feature.
  211. void ImGui::ShowDemoWindow(bool* p_open)
  212. {
  213. // Exceptionally add an extra assert here for people confused about initial Dear ImGui setup
  214. // Most ImGui functions would normally just crash if the context is missing.
  215. IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing dear imgui context. Refer to examples app!");
  216. // Examples Apps (accessible from the "Examples" menu)
  217. static bool show_app_main_menu_bar = false;
  218. static bool show_app_dockspace = false;
  219. static bool show_app_documents = false;
  220. static bool show_app_console = false;
  221. static bool show_app_log = false;
  222. static bool show_app_layout = false;
  223. static bool show_app_property_editor = false;
  224. static bool show_app_long_text = false;
  225. static bool show_app_auto_resize = false;
  226. static bool show_app_constrained_resize = false;
  227. static bool show_app_simple_overlay = false;
  228. static bool show_app_window_titles = false;
  229. static bool show_app_custom_rendering = false;
  230. if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
  231. if (show_app_dockspace) ShowExampleAppDockSpace(&show_app_dockspace); // Process the Docking app first, as explicit DockSpace() nodes needs to be submitted early (read comments near the DockSpace function)
  232. if (show_app_documents) ShowExampleAppDocuments(&show_app_documents); // Process the Document app next, as it may also use a DockSpace()
  233. if (show_app_console) ShowExampleAppConsole(&show_app_console);
  234. if (show_app_log) ShowExampleAppLog(&show_app_log);
  235. if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
  236. if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor);
  237. if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
  238. if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
  239. if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize);
  240. if (show_app_simple_overlay) ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
  241. if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles);
  242. if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);
  243. // Dear ImGui Apps (accessible from the "Tools" menu)
  244. static bool show_app_metrics = false;
  245. static bool show_app_style_editor = false;
  246. static bool show_app_about = false;
  247. if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); }
  248. if (show_app_about) { ImGui::ShowAboutWindow(&show_app_about); }
  249. if (show_app_style_editor)
  250. {
  251. ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor);
  252. ImGui::ShowStyleEditor();
  253. ImGui::End();
  254. }
  255. // Demonstrate the various window flags. Typically you would just use the default!
  256. static bool no_titlebar = false;
  257. static bool no_scrollbar = false;
  258. static bool no_menu = false;
  259. static bool no_move = false;
  260. static bool no_resize = false;
  261. static bool no_collapse = false;
  262. static bool no_close = false;
  263. static bool no_nav = false;
  264. static bool no_background = false;
  265. static bool no_bring_to_front = false;
  266. static bool no_docking = false;
  267. ImGuiWindowFlags window_flags = 0;
  268. if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
  269. if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
  270. if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar;
  271. if (no_move) window_flags |= ImGuiWindowFlags_NoMove;
  272. if (no_resize) window_flags |= ImGuiWindowFlags_NoResize;
  273. if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
  274. if (no_nav) window_flags |= ImGuiWindowFlags_NoNav;
  275. if (no_background) window_flags |= ImGuiWindowFlags_NoBackground;
  276. if (no_bring_to_front) window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
  277. if (no_docking) window_flags |= ImGuiWindowFlags_NoDocking;
  278. if (no_close) p_open = NULL; // Don't pass our bool* to Begin
  279. // We specify a default position/size in case there's no data in the .ini file.
  280. // We only do it to make the demo applications a little more welcoming, but typically this isn't required.
  281. ImGuiViewport* main_viewport = ImGui::GetMainViewport();
  282. ImGui::SetNextWindowPos(ImVec2(main_viewport->GetWorkPos().x + 650, main_viewport->GetWorkPos().y + 20), ImGuiCond_FirstUseEver);
  283. ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
  284. // Main body of the Demo window starts here.
  285. if (!ImGui::Begin("Dear ImGui Demo", p_open, window_flags))
  286. {
  287. // Early out if the window is collapsed, as an optimization.
  288. ImGui::End();
  289. return;
  290. }
  291. // Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details.
  292. // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align)
  293. //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f);
  294. // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets.
  295. ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
  296. // Menu Bar
  297. if (ImGui::BeginMenuBar())
  298. {
  299. if (ImGui::BeginMenu("Menu"))
  300. {
  301. ShowExampleMenuFile();
  302. ImGui::EndMenu();
  303. }
  304. if (ImGui::BeginMenu("Examples"))
  305. {
  306. ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
  307. ImGui::MenuItem("Console", NULL, &show_app_console);
  308. ImGui::MenuItem("Log", NULL, &show_app_log);
  309. ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
  310. ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
  311. ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
  312. ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
  313. ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
  314. ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
  315. ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
  316. ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
  317. ImGui::MenuItem("Dockspace", NULL, &show_app_dockspace);
  318. ImGui::MenuItem("Documents", NULL, &show_app_documents);
  319. ImGui::EndMenu();
  320. }
  321. if (ImGui::BeginMenu("Tools"))
  322. {
  323. ImGui::MenuItem("Metrics/Debugger", NULL, &show_app_metrics);
  324. ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
  325. ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
  326. ImGui::EndMenu();
  327. }
  328. ImGui::EndMenuBar();
  329. }
  330. ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
  331. ImGui::Spacing();
  332. if (ImGui::CollapsingHeader("Help"))
  333. {
  334. ImGui::Text("ABOUT THIS DEMO:");
  335. ImGui::BulletText("Sections below are demonstrating many aspects of the library.");
  336. ImGui::BulletText("The \"Examples\" menu above leads to more demo contents.");
  337. ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
  338. "and Metrics/Debugger (general purpose Dear ImGui debugging tool).");
  339. ImGui::Separator();
  340. ImGui::Text("PROGRAMMER GUIDE:");
  341. ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
  342. ImGui::BulletText("See comments in imgui.cpp.");
  343. ImGui::BulletText("See example applications in the examples/ folder.");
  344. ImGui::BulletText("Read the FAQ at http://www.dearimgui.org/faq/");
  345. ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
  346. ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
  347. ImGui::Separator();
  348. ImGui::Text("USER GUIDE:");
  349. ImGui::ShowUserGuide();
  350. }
  351. if (ImGui::CollapsingHeader("Configuration"))
  352. {
  353. ImGuiIO& io = ImGui::GetIO();
  354. if (ImGui::TreeNode("Configuration##2"))
  355. {
  356. ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
  357. ImGui::SameLine(); HelpMarker("Enable keyboard controls.");
  358. ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", &io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
  359. ImGui::SameLine(); HelpMarker("Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
  360. ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", &io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
  361. ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
  362. ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", &io.ConfigFlags, ImGuiConfigFlags_NoMouse);
  363. if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
  364. {
  365. // The "NoMouse" option can get us stuck with a disabled mouse! Let's provide an alternative way to fix it:
  366. if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
  367. {
  368. ImGui::SameLine();
  369. ImGui::Text("<<PRESS SPACE TO DISABLE>>");
  370. }
  371. if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
  372. io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
  373. }
  374. ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
  375. ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility.");
  376. ImGui::CheckboxFlags("io.ConfigFlags: DockingEnable", &io.ConfigFlags, ImGuiConfigFlags_DockingEnable);
  377. ImGui::SameLine(); HelpMarker(io.ConfigDockingWithShift ? "[beta] Use SHIFT to dock window into each others." : "[beta] Drag from title bar to dock windows into each others.");
  378. if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
  379. {
  380. ImGui::Indent();
  381. ImGui::Checkbox("io.ConfigDockingNoSplit", &io.ConfigDockingNoSplit);
  382. ImGui::SameLine(); HelpMarker("Simplified docking mode: disable window splitting, so docking is limited to merging multiple windows together into tab-bars.");
  383. ImGui::Checkbox("io.ConfigDockingWithShift", &io.ConfigDockingWithShift);
  384. ImGui::SameLine(); HelpMarker("Enable docking when holding Shift only (allows to drop in wider space, reduce visual noise)");
  385. ImGui::Checkbox("io.ConfigDockingAlwaysTabBar", &io.ConfigDockingAlwaysTabBar);
  386. ImGui::SameLine(); HelpMarker("Create a docking node and tab-bar on single floating windows.");
  387. ImGui::Checkbox("io.ConfigDockingTransparentPayload", &io.ConfigDockingTransparentPayload);
  388. ImGui::SameLine(); HelpMarker("Make window or viewport transparent when docking and only display docking boxes on the target viewport. Useful if rendering of multiple viewport cannot be synced. Best used with ConfigViewportsNoAutoMerge.");
  389. ImGui::Unindent();
  390. }
  391. ImGui::CheckboxFlags("io.ConfigFlags: ViewportsEnable", &io.ConfigFlags, ImGuiConfigFlags_ViewportsEnable);
  392. ImGui::SameLine(); HelpMarker("[beta] Enable beta multi-viewports support. See ImGuiPlatformIO for details.");
  393. if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
  394. {
  395. ImGui::Indent();
  396. ImGui::Checkbox("io.ConfigViewportsNoAutoMerge", &io.ConfigViewportsNoAutoMerge);
  397. ImGui::SameLine(); HelpMarker("Set to make all floating imgui windows always create their own viewport. Otherwise, they are merged into the main host viewports when overlapping it.");
  398. ImGui::Checkbox("io.ConfigViewportsNoTaskBarIcon", &io.ConfigViewportsNoTaskBarIcon);
  399. ImGui::SameLine(); HelpMarker("Toggling this at runtime is normally unsupported (most platform backends won't refresh the task bar icon state right away).");
  400. ImGui::Checkbox("io.ConfigViewportsNoDecoration", &io.ConfigViewportsNoDecoration);
  401. ImGui::SameLine(); HelpMarker("Toggling this at runtime is normally unsupported (most platform backends won't refresh the decoration right away).");
  402. ImGui::Checkbox("io.ConfigViewportsNoDefaultParent", &io.ConfigViewportsNoDefaultParent);
  403. ImGui::SameLine(); HelpMarker("Toggling this at runtime is normally unsupported (most platform backends won't refresh the parenting right away).");
  404. ImGui::Unindent();
  405. }
  406. ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
  407. ImGui::SameLine(); HelpMarker("Set to false to disable blinking cursor, for users who consider it distracting");
  408. ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
  409. ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
  410. ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
  411. ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
  412. ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
  413. ImGui::Text("Also see Style->Rendering for rendering options.");
  414. ImGui::TreePop();
  415. ImGui::Separator();
  416. }
  417. if (ImGui::TreeNode("Backend Flags"))
  418. {
  419. HelpMarker(
  420. "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n"
  421. "Here we expose then as read-only fields to avoid breaking interactions with your backend.");
  422. // Make a local copy to avoid modifying actual backend flags.
  423. ImGuiBackendFlags backend_flags = io.BackendFlags;
  424. ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &backend_flags, ImGuiBackendFlags_HasGamepad);
  425. ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &backend_flags, ImGuiBackendFlags_HasMouseCursors);
  426. ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &backend_flags, ImGuiBackendFlags_HasSetMousePos);
  427. ImGui::CheckboxFlags("io.BackendFlags: PlatformHasViewports", &backend_flags, ImGuiBackendFlags_PlatformHasViewports);
  428. ImGui::CheckboxFlags("io.BackendFlags: HasMouseHoveredViewport",&backend_flags, ImGuiBackendFlags_HasMouseHoveredViewport);
  429. ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &backend_flags, ImGuiBackendFlags_RendererHasVtxOffset);
  430. ImGui::CheckboxFlags("io.BackendFlags: RendererHasViewports", &backend_flags, ImGuiBackendFlags_RendererHasViewports);
  431. ImGui::TreePop();
  432. ImGui::Separator();
  433. }
  434. if (ImGui::TreeNode("Style"))
  435. {
  436. HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function.");
  437. ImGui::ShowStyleEditor();
  438. ImGui::TreePop();
  439. ImGui::Separator();
  440. }
  441. if (ImGui::TreeNode("Capture/Logging"))
  442. {
  443. HelpMarker(
  444. "The logging API redirects all text output so you can easily capture the content of "
  445. "a window or a block. Tree nodes can be automatically expanded.\n"
  446. "Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
  447. ImGui::LogButtons();
  448. HelpMarker("You can also call ImGui::LogText() to output directly to the log without a visual output.");
  449. if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
  450. {
  451. ImGui::LogToClipboard();
  452. ImGui::LogText("Hello, world!");
  453. ImGui::LogFinish();
  454. }
  455. ImGui::TreePop();
  456. }
  457. }
  458. if (ImGui::CollapsingHeader("Window options"))
  459. {
  460. ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
  461. ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
  462. ImGui::Checkbox("No menu", &no_menu);
  463. ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
  464. ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300);
  465. ImGui::Checkbox("No collapse", &no_collapse);
  466. ImGui::Checkbox("No close", &no_close); ImGui::SameLine(150);
  467. ImGui::Checkbox("No nav", &no_nav); ImGui::SameLine(300);
  468. ImGui::Checkbox("No background", &no_background);
  469. ImGui::Checkbox("No bring to front", &no_bring_to_front);
  470. ImGui::Checkbox("No docking", &no_docking);
  471. }
  472. // All demo contents
  473. ShowDemoWindowWidgets();
  474. ShowDemoWindowLayout();
  475. ShowDemoWindowPopups();
  476. ShowDemoWindowColumns();
  477. ShowDemoWindowMisc();
  478. // End of ShowDemoWindow()
  479. ImGui::PopItemWidth();
  480. ImGui::End();
  481. }
  482. static void ShowDemoWindowWidgets()
  483. {
  484. if (!ImGui::CollapsingHeader("Widgets"))
  485. return;
  486. if (ImGui::TreeNode("Basic"))
  487. {
  488. static int clicked = 0;
  489. if (ImGui::Button("Button"))
  490. clicked++;
  491. if (clicked & 1)
  492. {
  493. ImGui::SameLine();
  494. ImGui::Text("Thanks for clicking me!");
  495. }
  496. static bool check = true;
  497. ImGui::Checkbox("checkbox", &check);
  498. static int e = 0;
  499. ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
  500. ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
  501. ImGui::RadioButton("radio c", &e, 2);
  502. // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
  503. for (int i = 0; i < 7; i++)
  504. {
  505. if (i > 0)
  506. ImGui::SameLine();
  507. ImGui::PushID(i);
  508. ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f));
  509. ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f));
  510. ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f));
  511. ImGui::Button("Click");
  512. ImGui::PopStyleColor(3);
  513. ImGui::PopID();
  514. }
  515. // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements
  516. // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!)
  517. // See 'Demo->Layout->Text Baseline Alignment' for details.
  518. ImGui::AlignTextToFramePadding();
  519. ImGui::Text("Hold to repeat:");
  520. ImGui::SameLine();
  521. // Arrow buttons with Repeater
  522. static int counter = 0;
  523. float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
  524. ImGui::PushButtonRepeat(true);
  525. if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
  526. ImGui::SameLine(0.0f, spacing);
  527. if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
  528. ImGui::PopButtonRepeat();
  529. ImGui::SameLine();
  530. ImGui::Text("%d", counter);
  531. ImGui::Text("Hover over me");
  532. if (ImGui::IsItemHovered())
  533. ImGui::SetTooltip("I am a tooltip");
  534. ImGui::SameLine();
  535. ImGui::Text("- or me");
  536. if (ImGui::IsItemHovered())
  537. {
  538. ImGui::BeginTooltip();
  539. ImGui::Text("I am a fancy tooltip");
  540. static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
  541. ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
  542. ImGui::EndTooltip();
  543. }
  544. ImGui::Separator();
  545. ImGui::LabelText("label", "Value");
  546. {
  547. // Using the _simplified_ one-liner Combo() api here
  548. // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api.
  549. const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
  550. static int item_current = 0;
  551. ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
  552. ImGui::SameLine(); HelpMarker(
  553. "Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, "
  554. "and demonstration of various flags.\n");
  555. }
  556. {
  557. // To wire InputText() with std::string or any other custom string type,
  558. // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
  559. static char str0[128] = "Hello, world!";
  560. ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
  561. ImGui::SameLine(); HelpMarker(
  562. "USER:\n"
  563. "Hold SHIFT or use mouse to select text.\n"
  564. "CTRL+Left/Right to word jump.\n"
  565. "CTRL+A or double-click to select all.\n"
  566. "CTRL+X,CTRL+C,CTRL+V clipboard.\n"
  567. "CTRL+Z,CTRL+Y undo/redo.\n"
  568. "ESCAPE to revert.\n\n"
  569. "PROGRAMMER:\n"
  570. "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() "
  571. "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated "
  572. "in imgui_demo.cpp).");
  573. static char str1[128] = "";
  574. ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));
  575. static int i0 = 123;
  576. ImGui::InputInt("input int", &i0);
  577. ImGui::SameLine(); HelpMarker(
  578. "You can apply arithmetic operators +,*,/ on numerical values.\n"
  579. " e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\n"
  580. "Use +- to subtract.");
  581. static float f0 = 0.001f;
  582. ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
  583. static double d0 = 999999.00000001;
  584. ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");
  585. static float f1 = 1.e10f;
  586. ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
  587. ImGui::SameLine(); HelpMarker(
  588. "You can input value using the scientific notation,\n"
  589. " e.g. \"1e+8\" becomes \"100000000\".");
  590. static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
  591. ImGui::InputFloat3("input float3", vec4a);
  592. }
  593. {
  594. static int i1 = 50, i2 = 42;
  595. ImGui::DragInt("drag int", &i1, 1);
  596. ImGui::SameLine(); HelpMarker(
  597. "Click and drag to edit value.\n"
  598. "Hold SHIFT/ALT for faster/slower edit.\n"
  599. "Double-click or CTRL+click to input value.");
  600. ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp);
  601. static float f1 = 1.00f, f2 = 0.0067f;
  602. ImGui::DragFloat("drag float", &f1, 0.005f);
  603. ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
  604. }
  605. {
  606. static int i1 = 0;
  607. ImGui::SliderInt("slider int", &i1, -1, 3);
  608. ImGui::SameLine(); HelpMarker("CTRL+click to input value.");
  609. static float f1 = 0.123f, f2 = 0.0f;
  610. ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
  611. ImGui::SliderFloat("slider float (log)", &f2, -10.0f, 10.0f, "%.4f", ImGuiSliderFlags_Logarithmic);
  612. static float angle = 0.0f;
  613. ImGui::SliderAngle("slider angle", &angle);
  614. // Using the format string to display a name instead of an integer.
  615. // Here we completely omit '%d' from the format string, so it'll only display a name.
  616. // This technique can also be used with DragInt().
  617. enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT };
  618. static int elem = Element_Fire;
  619. const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
  620. const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
  621. ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name);
  622. ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
  623. }
  624. {
  625. static float col1[3] = { 1.0f, 0.0f, 0.2f };
  626. static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
  627. ImGui::ColorEdit3("color 1", col1);
  628. ImGui::SameLine(); HelpMarker(
  629. "Click on the color square to open a color picker.\n"
  630. "Click and hold to use drag and drop.\n"
  631. "Right-click on the color square to show options.\n"
  632. "CTRL+click on individual component to input value.\n");
  633. ImGui::ColorEdit4("color 2", col2);
  634. }
  635. {
  636. // List box
  637. const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
  638. static int item_current = 1;
  639. ImGui::ListBox("listbox\n(single select)", &item_current, items, IM_ARRAYSIZE(items), 4);
  640. //static int listbox_item_current2 = 2;
  641. //ImGui::SetNextItemWidth(-1);
  642. //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
  643. }
  644. ImGui::TreePop();
  645. }
  646. // Testing ImGuiOnceUponAFrame helper.
  647. //static ImGuiOnceUponAFrame once;
  648. //for (int i = 0; i < 5; i++)
  649. // if (once)
  650. // ImGui::Text("This will be displayed only once.");
  651. if (ImGui::TreeNode("Trees"))
  652. {
  653. if (ImGui::TreeNode("Basic trees"))
  654. {
  655. for (int i = 0; i < 5; i++)
  656. {
  657. // Use SetNextItemOpen() so set the default state of a node to be open. We could
  658. // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing!
  659. if (i == 0)
  660. ImGui::SetNextItemOpen(true, ImGuiCond_Once);
  661. if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
  662. {
  663. ImGui::Text("blah blah");
  664. ImGui::SameLine();
  665. if (ImGui::SmallButton("button")) {}
  666. ImGui::TreePop();
  667. }
  668. }
  669. ImGui::TreePop();
  670. }
  671. if (ImGui::TreeNode("Advanced, with Selectable nodes"))
  672. {
  673. HelpMarker(
  674. "This is a more typical looking tree with selectable nodes.\n"
  675. "Click to select, CTRL+Click to toggle, click on arrows or double-click to open.");
  676. static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
  677. static bool align_label_with_current_x_position = false;
  678. static bool test_drag_and_drop = false;
  679. ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", &base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
  680. ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
  681. ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
  682. ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
  683. ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
  684. ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
  685. ImGui::Text("Hello!");
  686. if (align_label_with_current_x_position)
  687. ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
  688. // 'selection_mask' is dumb representation of what may be user-side selection state.
  689. // You may retain selection state inside or outside your objects in whatever format you see fit.
  690. // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end
  691. /// of the loop. May be a pointer to your own node type, etc.
  692. static int selection_mask = (1 << 2);
  693. int node_clicked = -1;
  694. for (int i = 0; i < 6; i++)
  695. {
  696. // Disable the default "open on single-click behavior" + set Selected flag according to our selection.
  697. ImGuiTreeNodeFlags node_flags = base_flags;
  698. const bool is_selected = (selection_mask & (1 << i)) != 0;
  699. if (is_selected)
  700. node_flags |= ImGuiTreeNodeFlags_Selected;
  701. if (i < 3)
  702. {
  703. // Items 0..2 are Tree Node
  704. bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
  705. if (ImGui::IsItemClicked())
  706. node_clicked = i;
  707. if (test_drag_and_drop && ImGui::BeginDragDropSource())
  708. {
  709. ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
  710. ImGui::Text("This is a drag and drop source");
  711. ImGui::EndDragDropSource();
  712. }
  713. if (node_open)
  714. {
  715. ImGui::BulletText("Blah blah\nBlah Blah");
  716. ImGui::TreePop();
  717. }
  718. }
  719. else
  720. {
  721. // Items 3..5 are Tree Leaves
  722. // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
  723. // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
  724. node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
  725. ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
  726. if (ImGui::IsItemClicked())
  727. node_clicked = i;
  728. if (test_drag_and_drop && ImGui::BeginDragDropSource())
  729. {
  730. ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
  731. ImGui::Text("This is a drag and drop source");
  732. ImGui::EndDragDropSource();
  733. }
  734. }
  735. }
  736. if (node_clicked != -1)
  737. {
  738. // Update selection state
  739. // (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
  740. if (ImGui::GetIO().KeyCtrl)
  741. selection_mask ^= (1 << node_clicked); // CTRL+click to toggle
  742. else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection
  743. selection_mask = (1 << node_clicked); // Click to single-select
  744. }
  745. if (align_label_with_current_x_position)
  746. ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
  747. ImGui::TreePop();
  748. }
  749. ImGui::TreePop();
  750. }
  751. if (ImGui::TreeNode("Collapsing Headers"))
  752. {
  753. static bool closable_group = true;
  754. ImGui::Checkbox("Show 2nd header", &closable_group);
  755. if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None))
  756. {
  757. ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
  758. for (int i = 0; i < 5; i++)
  759. ImGui::Text("Some content %d", i);
  760. }
  761. if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
  762. {
  763. ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
  764. for (int i = 0; i < 5; i++)
  765. ImGui::Text("More content %d", i);
  766. }
  767. /*
  768. if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet))
  769. ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
  770. */
  771. ImGui::TreePop();
  772. }
  773. if (ImGui::TreeNode("Bullets"))
  774. {
  775. ImGui::BulletText("Bullet point 1");
  776. ImGui::BulletText("Bullet point 2\nOn multiple lines");
  777. if (ImGui::TreeNode("Tree node"))
  778. {
  779. ImGui::BulletText("Another bullet point");
  780. ImGui::TreePop();
  781. }
  782. ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
  783. ImGui::Bullet(); ImGui::SmallButton("Button");
  784. ImGui::TreePop();
  785. }
  786. if (ImGui::TreeNode("Text"))
  787. {
  788. if (ImGui::TreeNode("Colorful Text"))
  789. {
  790. // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
  791. ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink");
  792. ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow");
  793. ImGui::TextDisabled("Disabled");
  794. ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle.");
  795. ImGui::TreePop();
  796. }
  797. if (ImGui::TreeNode("Word Wrapping"))
  798. {
  799. // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
  800. ImGui::TextWrapped(
  801. "This text should automatically wrap on the edge of the window. The current implementation "
  802. "for text wrapping follows simple rules suitable for English and possibly other languages.");
  803. ImGui::Spacing();
  804. static float wrap_width = 200.0f;
  805. ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
  806. ImDrawList* draw_list = ImGui::GetWindowDrawList();
  807. for (int n = 0; n < 2; n++)
  808. {
  809. ImGui::Text("Test paragraph %d:", n);
  810. ImVec2 pos = ImGui::GetCursorScreenPos();
  811. ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y);
  812. ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight());
  813. ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
  814. if (n == 0)
  815. ImGui::Text("The lazy dog is a good dog. This paragraph should fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width);
  816. else
  817. ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh");
  818. // Draw actual text bounding box, following by marker of our expected limit (should not overlap!)
  819. draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
  820. draw_list->AddRectFilled(marker_min, marker_max, IM_COL32(255, 0, 255, 255));
  821. ImGui::PopTextWrapPos();
  822. }
  823. ImGui::TreePop();
  824. }
  825. if (ImGui::TreeNode("UTF-8 Text"))
  826. {
  827. // UTF-8 test with Japanese characters
  828. // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.)
  829. // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
  830. // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you
  831. // can save your source files as 'UTF-8 without signature').
  832. // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8
  833. // CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants.
  834. // Don't do this in your application! Please use u8"text in any language" in your application!
  835. // Note that characters values are preserved even by InputText() if the font cannot be displayed,
  836. // so you can safely copy & paste garbled characters into another application.
  837. ImGui::TextWrapped(
  838. "CJK text will only appears if the font was loaded with the appropriate CJK character ranges. "
  839. "Call io.Font->AddFontFromFileTTF() manually to load extra character ranges. "
  840. "Read docs/FONTS.md for details.");
  841. ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string.
  842. ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
  843. static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
  844. //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
  845. ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
  846. ImGui::TreePop();
  847. }
  848. ImGui::TreePop();
  849. }
  850. if (ImGui::TreeNode("Images"))
  851. {
  852. ImGuiIO& io = ImGui::GetIO();
  853. ImGui::TextWrapped(
  854. "Below we are displaying the font texture (which is the only texture we have access to in this demo). "
  855. "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. "
  856. "Hover the texture for a zoomed view!");
  857. // Below we are displaying the font texture because it is the only texture we have access to inside the demo!
  858. // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that
  859. // will be passed to the rendering backend via the ImDrawCmd structure.
  860. // If you use one of the default imgui_impl_XXXX.cpp rendering backend, they all have comments at the top
  861. // of their respective source file to specify what they expect to be stored in ImTextureID, for example:
  862. // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer
  863. // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc.
  864. // More:
  865. // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers
  866. // to ImGui::Image(), and gather width/height through your own functions, etc.
  867. // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer,
  868. // it will help you debug issues if you are confused about it.
  869. // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
  870. // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
  871. // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
  872. ImTextureID my_tex_id = io.Fonts->TexID;
  873. float my_tex_w = (float)io.Fonts->TexWidth;
  874. float my_tex_h = (float)io.Fonts->TexHeight;
  875. {
  876. ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
  877. ImVec2 pos = ImGui::GetCursorScreenPos();
  878. ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
  879. ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
  880. ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
  881. ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); // 50% opaque white
  882. ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
  883. if (ImGui::IsItemHovered())
  884. {
  885. ImGui::BeginTooltip();
  886. float region_sz = 32.0f;
  887. float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
  888. float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
  889. float zoom = 4.0f;
  890. if (region_x < 0.0f) { region_x = 0.0f; }
  891. else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
  892. if (region_y < 0.0f) { region_y = 0.0f; }
  893. else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
  894. ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
  895. ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
  896. ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
  897. ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
  898. ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, tint_col, border_col);
  899. ImGui::EndTooltip();
  900. }
  901. }
  902. ImGui::TextWrapped("And now some textured buttons..");
  903. static int pressed_count = 0;
  904. for (int i = 0; i < 8; i++)
  905. {
  906. ImGui::PushID(i);
  907. int frame_padding = -1 + i; // -1 == uses default padding (style.FramePadding)
  908. ImVec2 size = ImVec2(32.0f, 32.0f); // Size of the image we want to make visible
  909. ImVec2 uv0 = ImVec2(0.0f, 0.0f); // UV coordinates for lower-left
  910. ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h);// UV coordinates for (32,32) in our texture
  911. ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); // Black background
  912. ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
  913. if (ImGui::ImageButton(my_tex_id, size, uv0, uv1, frame_padding, bg_col, tint_col))
  914. pressed_count += 1;
  915. ImGui::PopID();
  916. ImGui::SameLine();
  917. }
  918. ImGui::NewLine();
  919. ImGui::Text("Pressed %d times.", pressed_count);
  920. ImGui::TreePop();
  921. }
  922. if (ImGui::TreeNode("Combo"))
  923. {
  924. // Expose flags as checkbox for the demo
  925. static ImGuiComboFlags flags = 0;
  926. ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft);
  927. ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo");
  928. if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton))
  929. flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both
  930. if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview))
  931. flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both
  932. // Using the generic BeginCombo() API, you have full control over how to display the combo contents.
  933. // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
  934. // stored in the object itself, etc.)
  935. const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
  936. static int item_current_idx = 0; // Here our selection data is an index.
  937. const char* combo_label = items[item_current_idx]; // Label to preview before opening the combo (technically it could be anything)
  938. if (ImGui::BeginCombo("combo 1", combo_label, flags))
  939. {
  940. for (int n = 0; n < IM_ARRAYSIZE(items); n++)
  941. {
  942. const bool is_selected = (item_current_idx == n);
  943. if (ImGui::Selectable(items[n], is_selected))
  944. item_current_idx = n;
  945. // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
  946. if (is_selected)
  947. ImGui::SetItemDefaultFocus();
  948. }
  949. ImGui::EndCombo();
  950. }
  951. // Simplified one-liner Combo() API, using values packed in a single constant string
  952. static int item_current_2 = 0;
  953. ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
  954. // Simplified one-liner Combo() using an array of const char*
  955. static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
  956. ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
  957. // Simplified one-liner Combo() using an accessor function
  958. struct Funcs { static bool ItemGetter(void* data, int n, const char** out_str) { *out_str = ((const char**)data)[n]; return true; } };
  959. static int item_current_4 = 0;
  960. ImGui::Combo("combo 4 (function)", &item_current_4, &Funcs::ItemGetter, items, IM_ARRAYSIZE(items));
  961. ImGui::TreePop();
  962. }
  963. if (ImGui::TreeNode("Selectables"))
  964. {
  965. // Selectable() has 2 overloads:
  966. // - The one taking "bool selected" as a read-only selection information.
  967. // When Selectable() has been clicked it returns true and you can alter selection state accordingly.
  968. // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
  969. // The earlier is more flexible, as in real application your selection may be stored in many different ways
  970. // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc).
  971. if (ImGui::TreeNode("Basic"))
  972. {
  973. static bool selection[5] = { false, true, false, false, false };
  974. ImGui::Selectable("1. I am selectable", &selection[0]);
  975. ImGui::Selectable("2. I am selectable", &selection[1]);
  976. ImGui::Text("3. I am not selectable");
  977. ImGui::Selectable("4. I am selectable", &selection[3]);
  978. if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick))
  979. if (ImGui::IsMouseDoubleClicked(0))
  980. selection[4] = !selection[4];
  981. ImGui::TreePop();
  982. }
  983. if (ImGui::TreeNode("Selection State: Single Selection"))
  984. {
  985. static int selected = -1;
  986. for (int n = 0; n < 5; n++)
  987. {
  988. char buf[32];
  989. sprintf(buf, "Object %d", n);
  990. if (ImGui::Selectable(buf, selected == n))
  991. selected = n;
  992. }
  993. ImGui::TreePop();
  994. }
  995. if (ImGui::TreeNode("Selection State: Multiple Selection"))
  996. {
  997. HelpMarker("Hold CTRL and click to select multiple items.");
  998. static bool selection[5] = { false, false, false, false, false };
  999. for (int n = 0; n < 5; n++)
  1000. {
  1001. char buf[32];
  1002. sprintf(buf, "Object %d", n);
  1003. if (ImGui::Selectable(buf, selection[n]))
  1004. {
  1005. if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held
  1006. memset(selection, 0, sizeof(selection));
  1007. selection[n] ^= 1;
  1008. }
  1009. }
  1010. ImGui::TreePop();
  1011. }
  1012. if (ImGui::TreeNode("Rendering more text into the same line"))
  1013. {
  1014. // Using the Selectable() override that takes "bool* p_selected" parameter,
  1015. // this function toggle your bool value automatically.
  1016. static bool selected[3] = { false, false, false };
  1017. ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
  1018. ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
  1019. ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
  1020. ImGui::TreePop();
  1021. }
  1022. if (ImGui::TreeNode("In columns"))
  1023. {
  1024. ImGui::Columns(3, NULL, false);
  1025. static bool selected[16] = {};
  1026. for (int i = 0; i < 16; i++)
  1027. {
  1028. char label[32]; sprintf(label, "Item %d", i);
  1029. if (ImGui::Selectable(label, &selected[i])) {}
  1030. ImGui::NextColumn();
  1031. }
  1032. ImGui::Columns(1);
  1033. ImGui::TreePop();
  1034. }
  1035. if (ImGui::TreeNode("Grid"))
  1036. {
  1037. static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
  1038. // Add in a bit of silly fun...
  1039. const float time = (float)ImGui::GetTime();
  1040. const bool winning_state = memchr(selected, 0, sizeof(selected)) == NULL; // If all cells are selected...
  1041. if (winning_state)
  1042. ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f + 0.5f * cosf(time * 2.0f), 0.5f + 0.5f * sinf(time * 3.0f)));
  1043. for (int y = 0; y < 4; y++)
  1044. for (int x = 0; x < 4; x++)
  1045. {
  1046. if (x > 0)
  1047. ImGui::SameLine();
  1048. ImGui::PushID(y * 4 + x);
  1049. if (ImGui::Selectable("Sailor", selected[y][x] != 0, 0, ImVec2(50, 50)))
  1050. {
  1051. // Toggle clicked cell + toggle neighbors
  1052. selected[y][x] ^= 1;
  1053. if (x > 0) { selected[y][x - 1] ^= 1; }
  1054. if (x < 3) { selected[y][x + 1] ^= 1; }
  1055. if (y > 0) { selected[y - 1][x] ^= 1; }
  1056. if (y < 3) { selected[y + 1][x] ^= 1; }
  1057. }
  1058. ImGui::PopID();
  1059. }
  1060. if (winning_state)
  1061. ImGui::PopStyleVar();
  1062. ImGui::TreePop();
  1063. }
  1064. if (ImGui::TreeNode("Alignment"))
  1065. {
  1066. HelpMarker(
  1067. "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item "
  1068. "basis using PushStyleVar(). You'll probably want to always keep your default situation to "
  1069. "left-align otherwise it becomes difficult to layout multiple items on a same line");
  1070. static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true };
  1071. for (int y = 0; y < 3; y++)
  1072. {
  1073. for (int x = 0; x < 3; x++)
  1074. {
  1075. ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f);
  1076. char name[32];
  1077. sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y);
  1078. if (x > 0) ImGui::SameLine();
  1079. ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment);
  1080. ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80));
  1081. ImGui::PopStyleVar();
  1082. }
  1083. }
  1084. ImGui::TreePop();
  1085. }
  1086. ImGui::TreePop();
  1087. }
  1088. // To wire InputText() with std::string or any other custom string type,
  1089. // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
  1090. if (ImGui::TreeNode("Text Input"))
  1091. {
  1092. if (ImGui::TreeNode("Multi-line Text Input"))
  1093. {
  1094. // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
  1095. // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
  1096. static char text[1024 * 16] =
  1097. "/*\n"
  1098. " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
  1099. " the hexadecimal encoding of one offending instruction,\n"
  1100. " more formally, the invalid operand with locked CMPXCHG8B\n"
  1101. " instruction bug, is a design flaw in the majority of\n"
  1102. " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
  1103. " processors (all in the P5 microarchitecture).\n"
  1104. "*/\n\n"
  1105. "label:\n"
  1106. "\tlock cmpxchg8b eax\n";
  1107. static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
  1108. HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include <string> in here)");
  1109. ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
  1110. ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput);
  1111. ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
  1112. ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
  1113. ImGui::TreePop();
  1114. }
  1115. if (ImGui::TreeNode("Filtered Text Input"))
  1116. {
  1117. struct TextFilters
  1118. {
  1119. // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i'
  1120. static int FilterImGuiLetters(ImGuiInputTextCallbackData* data)
  1121. {
  1122. if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar))
  1123. return 0;
  1124. return 1;
  1125. }
  1126. };
  1127. static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
  1128. static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
  1129. static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
  1130. static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
  1131. static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
  1132. static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
  1133. ImGui::TreePop();
  1134. }
  1135. if (ImGui::TreeNode("Password Input"))
  1136. {
  1137. static char password[64] = "password123";
  1138. ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
  1139. ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
  1140. ImGui::InputTextWithHint("password (w/ hint)", "<password>", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
  1141. ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password));
  1142. ImGui::TreePop();
  1143. }
  1144. if (ImGui::TreeNode("Completion, History, Edit Callbacks"))
  1145. {
  1146. struct Funcs
  1147. {
  1148. static int MyCallback(ImGuiInputTextCallbackData* data)
  1149. {
  1150. if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
  1151. {
  1152. data->InsertChars(data->CursorPos, "..");
  1153. }
  1154. else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory)
  1155. {
  1156. if (data->EventKey == ImGuiKey_UpArrow)
  1157. {
  1158. data->DeleteChars(0, data->BufTextLen);
  1159. data->InsertChars(0, "Pressed Up!");
  1160. data->SelectAll();
  1161. }
  1162. else if (data->EventKey == ImGuiKey_DownArrow)
  1163. {
  1164. data->DeleteChars(0, data->BufTextLen);
  1165. data->InsertChars(0, "Pressed Down!");
  1166. data->SelectAll();
  1167. }
  1168. }
  1169. else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit)
  1170. {
  1171. // Toggle casing of first character
  1172. char c = data->Buf[0];
  1173. if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32;
  1174. data->BufDirty = true;
  1175. // Increment a counter
  1176. int* p_int = (int*)data->UserData;
  1177. *p_int = *p_int + 1;
  1178. }
  1179. return 0;
  1180. }
  1181. };
  1182. static char buf1[64];
  1183. ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback);
  1184. ImGui::SameLine(); HelpMarker("Here we append \"..\" each time Tab is pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
  1185. static char buf2[64];
  1186. ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback);
  1187. ImGui::SameLine(); HelpMarker("Here we replace and select text each time Up/Down are pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
  1188. static char buf3[64];
  1189. static int edit_count = 0;
  1190. ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count);
  1191. ImGui::SameLine(); HelpMarker("Here we toggle the casing of the first character on every edits + count edits.");
  1192. ImGui::SameLine(); ImGui::Text("(%d)", edit_count);
  1193. ImGui::TreePop();
  1194. }
  1195. if (ImGui::TreeNode("Resize Callback"))
  1196. {
  1197. // To wire InputText() with std::string or any other custom string type,
  1198. // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper
  1199. // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string.
  1200. HelpMarker(
  1201. "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n"
  1202. "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string.");
  1203. struct Funcs
  1204. {
  1205. static int MyResizeCallback(ImGuiInputTextCallbackData* data)
  1206. {
  1207. if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
  1208. {
  1209. ImVector<char>* my_str = (ImVector<char>*)data->UserData;
  1210. IM_ASSERT(my_str->begin() == data->Buf);
  1211. my_str->resize(data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1
  1212. data->Buf = my_str->begin();
  1213. }
  1214. return 0;
  1215. }
  1216. // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace.
  1217. // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)'
  1218. static bool MyInputTextMultiline(const char* label, ImVector<char>* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0)
  1219. {
  1220. IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
  1221. return ImGui::InputTextMultiline(label, my_str->begin(), (size_t)my_str->size(), size, flags | ImGuiInputTextFlags_CallbackResize, Funcs::MyResizeCallback, (void*)my_str);
  1222. }
  1223. };
  1224. // For this demo we are using ImVector as a string container.
  1225. // Note that because we need to store a terminating zero character, our size/capacity are 1 more
  1226. // than usually reported by a typical string class.
  1227. static ImVector<char> my_str;
  1228. if (my_str.empty())
  1229. my_str.push_back(0);
  1230. Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16));
  1231. ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity());
  1232. ImGui::TreePop();
  1233. }
  1234. ImGui::TreePop();
  1235. }
  1236. // Plot/Graph widgets are currently fairly limited.
  1237. // Consider writing your own plotting widget, or using a third-party one
  1238. // (for third-party Plot widgets, see 'Wiki->Useful Widgets' or https://github.com/ocornut/imgui/labels/plot%2Fgraph)
  1239. if (ImGui::TreeNode("Plots Widgets"))
  1240. {
  1241. static bool animate = true;
  1242. ImGui::Checkbox("Animate", &animate);
  1243. static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
  1244. ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
  1245. // Fill an array of contiguous float values to plot
  1246. // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float
  1247. // and the sizeof() of your structure in the "stride" parameter.
  1248. static float values[90] = {};
  1249. static int values_offset = 0;
  1250. static double refresh_time = 0.0;
  1251. if (!animate || refresh_time == 0.0)
  1252. refresh_time = ImGui::GetTime();
  1253. while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo
  1254. {
  1255. static float phase = 0.0f;
  1256. values[values_offset] = cosf(phase);
  1257. values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
  1258. phase += 0.10f * values_offset;
  1259. refresh_time += 1.0f / 60.0f;
  1260. }
  1261. // Plots can display overlay texts
  1262. // (in this example, we will display an average value)
  1263. {
  1264. float average = 0.0f;
  1265. for (int n = 0; n < IM_ARRAYSIZE(values); n++)
  1266. average += values[n];
  1267. average /= (float)IM_ARRAYSIZE(values);
  1268. char overlay[32];
  1269. sprintf(overlay, "avg %f", average);
  1270. ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f));
  1271. }
  1272. ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
  1273. // Use functions to generate output
  1274. // FIXME: This is rather awkward because current plot API only pass in indices.
  1275. // We probably want an API passing floats and user provide sample rate/count.
  1276. struct Funcs
  1277. {
  1278. static float Sin(void*, int i) { return sinf(i * 0.1f); }
  1279. static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
  1280. };
  1281. static int func_type = 0, display_count = 70;
  1282. ImGui::Separator();
  1283. ImGui::SetNextItemWidth(100);
  1284. ImGui::Combo("func", &func_type, "Sin\0Saw\0");
  1285. ImGui::SameLine();
  1286. ImGui::SliderInt("Sample count", &display_count, 1, 400);
  1287. float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
  1288. ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
  1289. ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
  1290. ImGui::Separator();
  1291. // Animate a simple progress bar
  1292. static float progress = 0.0f, progress_dir = 1.0f;
  1293. if (animate)
  1294. {
  1295. progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
  1296. if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
  1297. if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
  1298. }
  1299. // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
  1300. // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
  1301. ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
  1302. ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
  1303. ImGui::Text("Progress Bar");
  1304. float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f);
  1305. char buf[32];
  1306. sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
  1307. ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
  1308. ImGui::TreePop();
  1309. }
  1310. if (ImGui::TreeNode("Color/Picker Widgets"))
  1311. {
  1312. static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f);
  1313. static bool alpha_preview = true;
  1314. static bool alpha_half_preview = false;
  1315. static bool drag_and_drop = true;
  1316. static bool options_menu = true;
  1317. static bool hdr = false;
  1318. ImGui::Checkbox("With Alpha Preview", &alpha_preview);
  1319. ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
  1320. ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
  1321. ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options.");
  1322. ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
  1323. ImGuiColorEditFlags misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
  1324. ImGui::Text("Color widget:");
  1325. ImGui::SameLine(); HelpMarker(
  1326. "Click on the color square to open a color picker.\n"
  1327. "CTRL+click on individual component to input value.\n");
  1328. ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
  1329. ImGui::Text("Color widget HSV with Alpha:");
  1330. ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | misc_flags);
  1331. ImGui::Text("Color widget with Float Display:");
  1332. ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
  1333. ImGui::Text("Color button with Picker:");
  1334. ImGui::SameLine(); HelpMarker(
  1335. "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n"
  1336. "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only "
  1337. "be used for the tooltip and picker popup.");
  1338. ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
  1339. ImGui::Text("Color button with Custom Picker Popup:");
  1340. // Generate a default palette. The palette will persist and can be edited.
  1341. static bool saved_palette_init = true;
  1342. static ImVec4 saved_palette[32] = {};
  1343. if (saved_palette_init)
  1344. {
  1345. for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
  1346. {
  1347. ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f,
  1348. saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
  1349. saved_palette[n].w = 1.0f; // Alpha
  1350. }
  1351. saved_palette_init = false;
  1352. }
  1353. static ImVec4 backup_color;
  1354. bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
  1355. ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
  1356. open_popup |= ImGui::Button("Palette");
  1357. if (open_popup)
  1358. {
  1359. ImGui::OpenPopup("mypicker");
  1360. backup_color = color;
  1361. }
  1362. if (ImGui::BeginPopup("mypicker"))
  1363. {
  1364. ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
  1365. ImGui::Separator();
  1366. ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
  1367. ImGui::SameLine();
  1368. ImGui::BeginGroup(); // Lock X position
  1369. ImGui::Text("Current");
  1370. ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40));
  1371. ImGui::Text("Previous");
  1372. if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)))
  1373. color = backup_color;
  1374. ImGui::Separator();
  1375. ImGui::Text("Palette");
  1376. for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
  1377. {
  1378. ImGui::PushID(n);
  1379. if ((n % 8) != 0)
  1380. ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
  1381. ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
  1382. if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20)))
  1383. color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
  1384. // Allow user to drop colors into each palette entry. Note that ColorButton() is already a
  1385. // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag.
  1386. if (ImGui::BeginDragDropTarget())
  1387. {
  1388. if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
  1389. memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
  1390. if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
  1391. memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
  1392. ImGui::EndDragDropTarget();
  1393. }
  1394. ImGui::PopID();
  1395. }
  1396. ImGui::EndGroup();
  1397. ImGui::EndPopup();
  1398. }
  1399. ImGui::Text("Color button only:");
  1400. static bool no_border = false;
  1401. ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border);
  1402. ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80));
  1403. ImGui::Text("Color picker:");
  1404. static bool alpha = true;
  1405. static bool alpha_bar = true;
  1406. static bool side_preview = true;
  1407. static bool ref_color = false;
  1408. static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
  1409. static int display_mode = 0;
  1410. static int picker_mode = 0;
  1411. ImGui::Checkbox("With Alpha", &alpha);
  1412. ImGui::Checkbox("With Alpha Bar", &alpha_bar);
  1413. ImGui::Checkbox("With Side Preview", &side_preview);
  1414. if (side_preview)
  1415. {
  1416. ImGui::SameLine();
  1417. ImGui::Checkbox("With Ref Color", &ref_color);
  1418. if (ref_color)
  1419. {
  1420. ImGui::SameLine();
  1421. ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
  1422. }
  1423. }
  1424. ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
  1425. ImGui::SameLine(); HelpMarker(
  1426. "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
  1427. "but the user can change it with a right-click.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
  1428. "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
  1429. ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
  1430. ImGui::SameLine(); HelpMarker("User can right-click the picker to change mode.");
  1431. ImGuiColorEditFlags flags = misc_flags;
  1432. if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
  1433. if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
  1434. if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
  1435. if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
  1436. if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
  1437. if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs; // Disable all RGB/HSV/Hex displays
  1438. if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB; // Override display mode
  1439. if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV;
  1440. if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex;
  1441. ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
  1442. ImGui::Text("Set defaults in code:");
  1443. ImGui::SameLine(); HelpMarker(
  1444. "SetColorEditOptions() is designed to allow you to set boot-time default.\n"
  1445. "We don't have Push/Pop functions because you can force options on a per-widget basis if needed,"
  1446. "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid"
  1447. "encouraging you to persistently save values that aren't forward-compatible.");
  1448. if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
  1449. ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
  1450. if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
  1451. ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
  1452. // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0)
  1453. static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV!
  1454. ImGui::Spacing();
  1455. ImGui::Text("HSV encoded colors");
  1456. ImGui::SameLine(); HelpMarker(
  1457. "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV"
  1458. "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the"
  1459. "added benefit that you can manipulate hue values with the picker even when saturation or value are zero.");
  1460. ImGui::Text("Color widget with InputHSV:");
  1461. ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
  1462. ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
  1463. ImGui::DragFloat4("Raw HSV values", (float*)&color_hsv, 0.01f, 0.0f, 1.0f);
  1464. ImGui::TreePop();
  1465. }
  1466. if (ImGui::TreeNode("Drag/Slider Flags"))
  1467. {
  1468. // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same!
  1469. static ImGuiSliderFlags flags = ImGuiSliderFlags_None;
  1470. ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp);
  1471. ImGui::SameLine(); HelpMarker("Always clamp value to min/max bounds (if any) when input manually with CTRL+Click.");
  1472. ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic);
  1473. ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values).");
  1474. ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat);
  1475. ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
  1476. ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput);
  1477. ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
  1478. // Drags
  1479. static float drag_f = 0.5f;
  1480. static int drag_i = 50;
  1481. ImGui::Text("Underlying float value: %f", drag_f);
  1482. ImGui::DragFloat("DragFloat (0 -> 1)", &drag_f, 0.005f, 0.0f, 1.0f, "%.3f", flags);
  1483. ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags);
  1484. ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags);
  1485. ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags);
  1486. ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags);
  1487. // Sliders
  1488. static float slider_f = 0.5f;
  1489. static int slider_i = 50;
  1490. ImGui::Text("Underlying float value: %f", slider_f);
  1491. ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags);
  1492. ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags);
  1493. ImGui::TreePop();
  1494. }
  1495. if (ImGui::TreeNode("Range Widgets"))
  1496. {
  1497. static float begin = 10, end = 90;
  1498. static int begin_i = 100, end_i = 1000;
  1499. ImGui::DragFloatRange2("range float", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%", ImGuiSliderFlags_AlwaysClamp);
  1500. ImGui::DragIntRange2("range int", &begin_i, &end_i, 5, 0, 1000, "Min: %d units", "Max: %d units");
  1501. ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
  1502. ImGui::TreePop();
  1503. }
  1504. if (ImGui::TreeNode("Data Types"))
  1505. {
  1506. // DragScalar/InputScalar/SliderScalar functions allow various data types
  1507. // - signed/unsigned
  1508. // - 8/16/32/64-bits
  1509. // - integer/float/double
  1510. // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum
  1511. // to pass the type, and passing all arguments by pointer.
  1512. // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types.
  1513. // In practice, if you frequently use a given type that is not covered by the normal API entry points,
  1514. // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*,
  1515. // and then pass their address to the generic function. For example:
  1516. // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
  1517. // {
  1518. // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
  1519. // }
  1520. // Setup limits (as helper variables so we can take their address, as explained above)
  1521. // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2.
  1522. #ifndef LLONG_MIN
  1523. ImS64 LLONG_MIN = -9223372036854775807LL - 1;
  1524. ImS64 LLONG_MAX = 9223372036854775807LL;
  1525. ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
  1526. #endif
  1527. const char s8_zero = 0, s8_one = 1, s8_fifty = 50, s8_min = -128, s8_max = 127;
  1528. const ImU8 u8_zero = 0, u8_one = 1, u8_fifty = 50, u8_min = 0, u8_max = 255;
  1529. const short s16_zero = 0, s16_one = 1, s16_fifty = 50, s16_min = -32768, s16_max = 32767;
  1530. const ImU16 u16_zero = 0, u16_one = 1, u16_fifty = 50, u16_min = 0, u16_max = 65535;
  1531. const ImS32 s32_zero = 0, s32_one = 1, s32_fifty = 50, s32_min = INT_MIN/2, s32_max = INT_MAX/2, s32_hi_a = INT_MAX/2 - 100, s32_hi_b = INT_MAX/2;
  1532. const ImU32 u32_zero = 0, u32_one = 1, u32_fifty = 50, u32_min = 0, u32_max = UINT_MAX/2, u32_hi_a = UINT_MAX/2 - 100, u32_hi_b = UINT_MAX/2;
  1533. const ImS64 s64_zero = 0, s64_one = 1, s64_fifty = 50, s64_min = LLONG_MIN/2, s64_max = LLONG_MAX/2, s64_hi_a = LLONG_MAX/2 - 100, s64_hi_b = LLONG_MAX/2;
  1534. const ImU64 u64_zero = 0, u64_one = 1, u64_fifty = 50, u64_min = 0, u64_max = ULLONG_MAX/2, u64_hi_a = ULLONG_MAX/2 - 100, u64_hi_b = ULLONG_MAX/2;
  1535. const float f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
  1536. const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
  1537. // State
  1538. static char s8_v = 127;
  1539. static ImU8 u8_v = 255;
  1540. static short s16_v = 32767;
  1541. static ImU16 u16_v = 65535;
  1542. static ImS32 s32_v = -1;
  1543. static ImU32 u32_v = (ImU32)-1;
  1544. static ImS64 s64_v = -1;
  1545. static ImU64 u64_v = (ImU64)-1;
  1546. static float f32_v = 0.123f;
  1547. static double f64_v = 90000.01234567890123456789;
  1548. const float drag_speed = 0.2f;
  1549. static bool drag_clamp = false;
  1550. ImGui::Text("Drags:");
  1551. ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp);
  1552. ImGui::SameLine(); HelpMarker(
  1553. "As with every widgets in dear imgui, we never modify values unless there is a user interaction.\n"
  1554. "You can override the clamping limits by using CTRL+Click to input a value.");
  1555. ImGui::DragScalar("drag s8", ImGuiDataType_S8, &s8_v, drag_speed, drag_clamp ? &s8_zero : NULL, drag_clamp ? &s8_fifty : NULL);
  1556. ImGui::DragScalar("drag u8", ImGuiDataType_U8, &u8_v, drag_speed, drag_clamp ? &u8_zero : NULL, drag_clamp ? &u8_fifty : NULL, "%u ms");
  1557. ImGui::DragScalar("drag s16", ImGuiDataType_S16, &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
  1558. ImGui::DragScalar("drag u16", ImGuiDataType_U16, &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms");
  1559. ImGui::DragScalar("drag s32", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
  1560. ImGui::DragScalar("drag u32", ImGuiDataType_U32, &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
  1561. ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
  1562. ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
  1563. ImGui::DragScalar("drag float", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f");
  1564. ImGui::DragScalar("drag float log", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", ImGuiSliderFlags_Logarithmic);
  1565. ImGui::DragScalar("drag double", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL, "%.10f grams");
  1566. ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic);
  1567. ImGui::Text("Sliders");
  1568. ImGui::SliderScalar("slider s8 full", ImGuiDataType_S8, &s8_v, &s8_min, &s8_max, "%d");
  1569. ImGui::SliderScalar("slider u8 full", ImGuiDataType_U8, &u8_v, &u8_min, &u8_max, "%u");
  1570. ImGui::SliderScalar("slider s16 full", ImGuiDataType_S16, &s16_v, &s16_min, &s16_max, "%d");
  1571. ImGui::SliderScalar("slider u16 full", ImGuiDataType_U16, &u16_v, &u16_min, &u16_max, "%u");
  1572. ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty,"%d");
  1573. ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32, &s32_v, &s32_hi_a, &s32_hi_b, "%d");
  1574. ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32, &s32_v, &s32_min, &s32_max, "%d");
  1575. ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u");
  1576. ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u");
  1577. ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u");
  1578. ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64, &s64_v, &s64_zero, &s64_fifty,"%I64d");
  1579. ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64, &s64_v, &s64_hi_a, &s64_hi_b, "%I64d");
  1580. ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64, &s64_v, &s64_min, &s64_max, "%I64d");
  1581. ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64, &u64_v, &u64_zero, &u64_fifty,"%I64u ms");
  1582. ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64, &u64_v, &u64_hi_a, &u64_hi_b, "%I64u ms");
  1583. ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64, &u64_v, &u64_min, &u64_max, "%I64u ms");
  1584. ImGui::SliderScalar("slider float low", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one);
  1585. ImGui::SliderScalar("slider float low log", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one, "%.10f", ImGuiSliderFlags_Logarithmic);
  1586. ImGui::SliderScalar("slider float high", ImGuiDataType_Float, &f32_v, &f32_lo_a, &f32_hi_a, "%e");
  1587. ImGui::SliderScalar("slider double low", ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f grams");
  1588. ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f", ImGuiSliderFlags_Logarithmic);
  1589. ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams");
  1590. ImGui::Text("Sliders (reverse)");
  1591. ImGui::SliderScalar("slider s8 reverse", ImGuiDataType_S8, &s8_v, &s8_max, &s8_min, "%d");
  1592. ImGui::SliderScalar("slider u8 reverse", ImGuiDataType_U8, &u8_v, &u8_max, &u8_min, "%u");
  1593. ImGui::SliderScalar("slider s32 reverse", ImGuiDataType_S32, &s32_v, &s32_fifty, &s32_zero, "%d");
  1594. ImGui::SliderScalar("slider u32 reverse", ImGuiDataType_U32, &u32_v, &u32_fifty, &u32_zero, "%u");
  1595. ImGui::SliderScalar("slider s64 reverse", ImGuiDataType_S64, &s64_v, &s64_fifty, &s64_zero, "%I64d");
  1596. ImGui::SliderScalar("slider u64 reverse", ImGuiDataType_U64, &u64_v, &u64_fifty, &u64_zero, "%I64u ms");
  1597. static bool inputs_step = true;
  1598. ImGui::Text("Inputs");
  1599. ImGui::Checkbox("Show step buttons", &inputs_step);
  1600. ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d");
  1601. ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u");
  1602. ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d");
  1603. ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u");
  1604. ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d");
  1605. ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
  1606. ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u");
  1607. ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
  1608. ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL);
  1609. ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL);
  1610. ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL);
  1611. ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL);
  1612. ImGui::TreePop();
  1613. }
  1614. if (ImGui::TreeNode("Multi-component Widgets"))
  1615. {
  1616. static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
  1617. static int vec4i[4] = { 1, 5, 100, 255 };
  1618. ImGui::InputFloat2("input float2", vec4f);
  1619. ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
  1620. ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
  1621. ImGui::InputInt2("input int2", vec4i);
  1622. ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
  1623. ImGui::SliderInt2("slider int2", vec4i, 0, 255);
  1624. ImGui::Spacing();
  1625. ImGui::InputFloat3("input float3", vec4f);
  1626. ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
  1627. ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
  1628. ImGui::InputInt3("input int3", vec4i);
  1629. ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
  1630. ImGui::SliderInt3("slider int3", vec4i, 0, 255);
  1631. ImGui::Spacing();
  1632. ImGui::InputFloat4("input float4", vec4f);
  1633. ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
  1634. ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
  1635. ImGui::InputInt4("input int4", vec4i);
  1636. ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
  1637. ImGui::SliderInt4("slider int4", vec4i, 0, 255);
  1638. ImGui::TreePop();
  1639. }
  1640. if (ImGui::TreeNode("Vertical Sliders"))
  1641. {
  1642. const float spacing = 4;
  1643. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
  1644. static int int_value = 0;
  1645. ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
  1646. ImGui::SameLine();
  1647. static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
  1648. ImGui::PushID("set1");
  1649. for (int i = 0; i < 7; i++)
  1650. {
  1651. if (i > 0) ImGui::SameLine();
  1652. ImGui::PushID(i);
  1653. ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f));
  1654. ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f));
  1655. ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f));
  1656. ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f));
  1657. ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, "");
  1658. if (ImGui::IsItemActive() || ImGui::IsItemHovered())
  1659. ImGui::SetTooltip("%.3f", values[i]);
  1660. ImGui::PopStyleColor(4);
  1661. ImGui::PopID();
  1662. }
  1663. ImGui::PopID();
  1664. ImGui::SameLine();
  1665. ImGui::PushID("set2");
  1666. static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
  1667. const int rows = 3;
  1668. const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
  1669. for (int nx = 0; nx < 4; nx++)
  1670. {
  1671. if (nx > 0) ImGui::SameLine();
  1672. ImGui::BeginGroup();
  1673. for (int ny = 0; ny < rows; ny++)
  1674. {
  1675. ImGui::PushID(nx * rows + ny);
  1676. ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
  1677. if (ImGui::IsItemActive() || ImGui::IsItemHovered())
  1678. ImGui::SetTooltip("%.3f", values2[nx]);
  1679. ImGui::PopID();
  1680. }
  1681. ImGui::EndGroup();
  1682. }
  1683. ImGui::PopID();
  1684. ImGui::SameLine();
  1685. ImGui::PushID("set3");
  1686. for (int i = 0; i < 4; i++)
  1687. {
  1688. if (i > 0) ImGui::SameLine();
  1689. ImGui::PushID(i);
  1690. ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
  1691. ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
  1692. ImGui::PopStyleVar();
  1693. ImGui::PopID();
  1694. }
  1695. ImGui::PopID();
  1696. ImGui::PopStyleVar();
  1697. ImGui::TreePop();
  1698. }
  1699. if (ImGui::TreeNode("Drag and Drop"))
  1700. {
  1701. if (ImGui::TreeNode("Drag and drop in standard widgets"))
  1702. {
  1703. // ColorEdit widgets automatically act as drag source and drag target.
  1704. // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F
  1705. // to allow your own widgets to use colors in their drag and drop interaction.
  1706. // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo.
  1707. HelpMarker("You can drag from the color squares.");
  1708. static float col1[3] = { 1.0f, 0.0f, 0.2f };
  1709. static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
  1710. ImGui::ColorEdit3("color 1", col1);
  1711. ImGui::ColorEdit4("color 2", col2);
  1712. ImGui::TreePop();
  1713. }
  1714. if (ImGui::TreeNode("Drag and drop to copy/swap items"))
  1715. {
  1716. enum Mode
  1717. {
  1718. Mode_Copy,
  1719. Mode_Move,
  1720. Mode_Swap
  1721. };
  1722. static int mode = 0;
  1723. if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
  1724. if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
  1725. if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
  1726. static const char* names[9] =
  1727. {
  1728. "Bobby", "Beatrice", "Betty",
  1729. "Brianna", "Barry", "Bernard",
  1730. "Bibi", "Blaine", "Bryn"
  1731. };
  1732. for (int n = 0; n < IM_ARRAYSIZE(names); n++)
  1733. {
  1734. ImGui::PushID(n);
  1735. if ((n % 3) != 0)
  1736. ImGui::SameLine();
  1737. ImGui::Button(names[n], ImVec2(60, 60));
  1738. // Our buttons are both drag sources and drag targets here!
  1739. if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
  1740. {
  1741. // Set payload to carry the index of our item (could be anything)
  1742. ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int));
  1743. // Display preview (could be anything, e.g. when dragging an image we could decide to display
  1744. // the filename and a small preview of the image, etc.)
  1745. if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); }
  1746. if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
  1747. if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
  1748. ImGui::EndDragDropSource();
  1749. }
  1750. if (ImGui::BeginDragDropTarget())
  1751. {
  1752. if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
  1753. {
  1754. IM_ASSERT(payload->DataSize == sizeof(int));
  1755. int payload_n = *(const int*)payload->Data;
  1756. if (mode == Mode_Copy)
  1757. {
  1758. names[n] = names[payload_n];
  1759. }
  1760. if (mode == Mode_Move)
  1761. {
  1762. names[n] = names[payload_n];
  1763. names[payload_n] = "";
  1764. }
  1765. if (mode == Mode_Swap)
  1766. {
  1767. const char* tmp = names[n];
  1768. names[n] = names[payload_n];
  1769. names[payload_n] = tmp;
  1770. }
  1771. }
  1772. ImGui::EndDragDropTarget();
  1773. }
  1774. ImGui::PopID();
  1775. }
  1776. ImGui::TreePop();
  1777. }
  1778. if (ImGui::TreeNode("Drag to reorder items (simple)"))
  1779. {
  1780. // Simple reordering
  1781. HelpMarker(
  1782. "We don't use the drag and drop api at all here! "
  1783. "Instead we query when the item is held but not hovered, and order items accordingly.");
  1784. static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
  1785. for (int n = 0; n < IM_ARRAYSIZE(item_names); n++)
  1786. {
  1787. const char* item = item_names[n];
  1788. ImGui::Selectable(item);
  1789. if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
  1790. {
  1791. int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
  1792. if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names))
  1793. {
  1794. item_names[n] = item_names[n_next];
  1795. item_names[n_next] = item;
  1796. ImGui::ResetMouseDragDelta();
  1797. }
  1798. }
  1799. }
  1800. ImGui::TreePop();
  1801. }
  1802. ImGui::TreePop();
  1803. }
  1804. if (ImGui::TreeNode("Querying Status (Active/Focused/Hovered etc.)"))
  1805. {
  1806. // Select an item type
  1807. const char* item_names[] =
  1808. {
  1809. "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat",
  1810. "InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "ListBox"
  1811. };
  1812. static int item_type = 1;
  1813. ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
  1814. ImGui::SameLine();
  1815. HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions.");
  1816. // Submit selected item item so we can query their status in the code following it.
  1817. bool ret = false;
  1818. static bool b = false;
  1819. static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
  1820. static char str[16] = {};
  1821. if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction
  1822. if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button
  1823. if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater)
  1824. if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox
  1825. if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item
  1826. if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing)
  1827. if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input
  1828. if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
  1829. if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
  1830. if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
  1831. if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node
  1832. if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
  1833. if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
  1834. // Display the values of IsItemHovered() and other common item state functions.
  1835. // Note that the ImGuiHoveredFlags_XXX flags can be combined.
  1836. // Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
  1837. // we query every state in a single call to avoid storing them and to simplify the code.
  1838. ImGui::BulletText(
  1839. "Return value = %d\n"
  1840. "IsItemFocused() = %d\n"
  1841. "IsItemHovered() = %d\n"
  1842. "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
  1843. "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
  1844. "IsItemHovered(_AllowWhenOverlapped) = %d\n"
  1845. "IsItemHovered(_RectOnly) = %d\n"
  1846. "IsItemActive() = %d\n"
  1847. "IsItemEdited() = %d\n"
  1848. "IsItemActivated() = %d\n"
  1849. "IsItemDeactivated() = %d\n"
  1850. "IsItemDeactivatedAfterEdit() = %d\n"
  1851. "IsItemVisible() = %d\n"
  1852. "IsItemClicked() = %d\n"
  1853. "IsItemToggledOpen() = %d\n"
  1854. "GetItemRectMin() = (%.1f, %.1f)\n"
  1855. "GetItemRectMax() = (%.1f, %.1f)\n"
  1856. "GetItemRectSize() = (%.1f, %.1f)",
  1857. ret,
  1858. ImGui::IsItemFocused(),
  1859. ImGui::IsItemHovered(),
  1860. ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
  1861. ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
  1862. ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
  1863. ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
  1864. ImGui::IsItemActive(),
  1865. ImGui::IsItemEdited(),
  1866. ImGui::IsItemActivated(),
  1867. ImGui::IsItemDeactivated(),
  1868. ImGui::IsItemDeactivatedAfterEdit(),
  1869. ImGui::IsItemVisible(),
  1870. ImGui::IsItemClicked(),
  1871. ImGui::IsItemToggledOpen(),
  1872. ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
  1873. ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
  1874. ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
  1875. );
  1876. static bool embed_all_inside_a_child_window = false;
  1877. ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
  1878. if (embed_all_inside_a_child_window)
  1879. ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), true);
  1880. // Testing IsWindowFocused() function with its various flags.
  1881. // Note that the ImGuiFocusedFlags_XXX flags can be combined.
  1882. ImGui::BulletText(
  1883. "IsWindowFocused() = %d\n"
  1884. "IsWindowFocused(_ChildWindows) = %d\n"
  1885. "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
  1886. "IsWindowFocused(_RootWindow) = %d\n"
  1887. "IsWindowFocused(_AnyWindow) = %d\n",
  1888. ImGui::IsWindowFocused(),
  1889. ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
  1890. ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
  1891. ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
  1892. ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
  1893. // Testing IsWindowHovered() function with its various flags.
  1894. // Note that the ImGuiHoveredFlags_XXX flags can be combined.
  1895. ImGui::BulletText(
  1896. "IsWindowHovered() = %d\n"
  1897. "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
  1898. "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
  1899. "IsWindowHovered(_ChildWindows) = %d\n"
  1900. "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
  1901. "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
  1902. "IsWindowHovered(_RootWindow) = %d\n"
  1903. "IsWindowHovered(_AnyWindow) = %d\n",
  1904. ImGui::IsWindowHovered(),
  1905. ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
  1906. ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
  1907. ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
  1908. ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
  1909. ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
  1910. ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
  1911. ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
  1912. ImGui::BeginChild("child", ImVec2(0, 50), true);
  1913. ImGui::Text("This is another child window for testing the _ChildWindows flag.");
  1914. ImGui::EndChild();
  1915. if (embed_all_inside_a_child_window)
  1916. ImGui::EndChild();
  1917. static char unused_str[] = "This widget is only here to be able to tab-out of the widgets above.";
  1918. ImGui::InputText("unused", unused_str, IM_ARRAYSIZE(unused_str), ImGuiInputTextFlags_ReadOnly);
  1919. // Calling IsItemHovered() after begin returns the hovered status of the title bar.
  1920. // This is useful in particular if you want to create a context menu associated to the title bar of a window.
  1921. // This will also work when docked into a Tab (the Tab replace the Title Bar and guarantee the same properties).
  1922. static bool test_window = false;
  1923. ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
  1924. if (test_window)
  1925. {
  1926. // FIXME-DOCK: This window cannot be docked within the ImGui Demo window, this will cause a feedback loop and get them stuck.
  1927. // Could we fix this through an ImGuiWindowClass feature? Or an API call to tag our parent as "don't skip items"?
  1928. ImGui::Begin("Title bar Hovered/Active tests", &test_window);
  1929. if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
  1930. {
  1931. if (ImGui::MenuItem("Close")) { test_window = false; }
  1932. ImGui::EndPopup();
  1933. }
  1934. ImGui::Text(
  1935. "IsItemHovered() after begin = %d (== is title bar hovered)\n"
  1936. "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
  1937. ImGui::IsItemHovered(), ImGui::IsItemActive());
  1938. ImGui::End();
  1939. }
  1940. ImGui::TreePop();
  1941. }
  1942. }
  1943. static void ShowDemoWindowLayout()
  1944. {
  1945. if (!ImGui::CollapsingHeader("Layout & Scrolling"))
  1946. return;
  1947. if (ImGui::TreeNode("Child windows"))
  1948. {
  1949. HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
  1950. static bool disable_mouse_wheel = false;
  1951. static bool disable_menu = false;
  1952. ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
  1953. ImGui::Checkbox("Disable Menu", &disable_menu);
  1954. // Child 1: no border, enable horizontal scrollbar
  1955. {
  1956. ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar;
  1957. if (disable_mouse_wheel)
  1958. window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
  1959. ImGui::BeginChild("ChildL", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags);
  1960. for (int i = 0; i < 100; i++)
  1961. ImGui::Text("%04d: scrollable region", i);
  1962. ImGui::EndChild();
  1963. }
  1964. ImGui::SameLine();
  1965. // Child 2: rounded border
  1966. {
  1967. ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
  1968. if (disable_mouse_wheel)
  1969. window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
  1970. if (!disable_menu)
  1971. window_flags |= ImGuiWindowFlags_MenuBar;
  1972. ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
  1973. ImGui::BeginChild("ChildR", ImVec2(0, 260), true, window_flags);
  1974. if (!disable_menu && ImGui::BeginMenuBar())
  1975. {
  1976. if (ImGui::BeginMenu("Menu"))
  1977. {
  1978. ShowExampleMenuFile();
  1979. ImGui::EndMenu();
  1980. }
  1981. ImGui::EndMenuBar();
  1982. }
  1983. ImGui::Columns(2);
  1984. for (int i = 0; i < 100; i++)
  1985. {
  1986. char buf[32];
  1987. sprintf(buf, "%03d", i);
  1988. ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
  1989. ImGui::NextColumn();
  1990. }
  1991. ImGui::EndChild();
  1992. ImGui::PopStyleVar();
  1993. }
  1994. ImGui::Separator();
  1995. // Demonstrate a few extra things
  1996. // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
  1997. // - Using SetCursorPos() to position child window (the child window is an item from the POV of parent window)
  1998. // You can also call SetNextWindowPos() to position the child window. The parent window will effectively
  1999. // layout from this position.
  2000. // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from
  2001. // the POV of the parent window). See 'Demo->Querying Status (Active/Focused/Hovered etc.)' for details.
  2002. {
  2003. static int offset_x = 0;
  2004. ImGui::SetNextItemWidth(100);
  2005. ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000);
  2006. ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
  2007. ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
  2008. ImGui::BeginChild("Red", ImVec2(200, 100), true, ImGuiWindowFlags_None);
  2009. for (int n = 0; n < 50; n++)
  2010. ImGui::Text("Some test %d", n);
  2011. ImGui::EndChild();
  2012. bool child_is_hovered = ImGui::IsItemHovered();
  2013. ImVec2 child_rect_min = ImGui::GetItemRectMin();
  2014. ImVec2 child_rect_max = ImGui::GetItemRectMax();
  2015. ImGui::PopStyleColor();
  2016. ImGui::Text("Hovered: %d", child_is_hovered);
  2017. ImGui::Text("Rect of child window is: (%.0f,%.0f) (%.0f,%.0f)", child_rect_min.x, child_rect_min.y, child_rect_max.x, child_rect_max.y);
  2018. }
  2019. ImGui::TreePop();
  2020. }
  2021. if (ImGui::TreeNode("Widgets Width"))
  2022. {
  2023. // Use SetNextItemWidth() to set the width of a single upcoming item.
  2024. // Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
  2025. // In real code use you'll probably want to choose width values that are proportional to your font size
  2026. // e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc.
  2027. static float f = 0.0f;
  2028. static bool show_indented_items = true;
  2029. ImGui::Checkbox("Show indented items", &show_indented_items);
  2030. ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
  2031. ImGui::SameLine(); HelpMarker("Fixed width.");
  2032. ImGui::PushItemWidth(100);
  2033. ImGui::DragFloat("float##1b", &f);
  2034. if (show_indented_items)
  2035. {
  2036. ImGui::Indent();
  2037. ImGui::DragFloat("float (indented)##1b", &f);
  2038. ImGui::Unindent();
  2039. }
  2040. ImGui::PopItemWidth();
  2041. ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");
  2042. ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
  2043. ImGui::PushItemWidth(-100);
  2044. ImGui::DragFloat("float##2a", &f);
  2045. if (show_indented_items)
  2046. {
  2047. ImGui::Indent();
  2048. ImGui::DragFloat("float (indented)##2b", &f);
  2049. ImGui::Unindent();
  2050. }
  2051. ImGui::PopItemWidth();
  2052. ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
  2053. ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
  2054. ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.5f);
  2055. ImGui::DragFloat("float##3a", &f);
  2056. if (show_indented_items)
  2057. {
  2058. ImGui::Indent();
  2059. ImGui::DragFloat("float (indented)##3b", &f);
  2060. ImGui::Unindent();
  2061. }
  2062. ImGui::PopItemWidth();
  2063. ImGui::Text("SetNextItemWidth/PushItemWidth(-GetContentRegionAvail().x * 0.5f)");
  2064. ImGui::SameLine(); HelpMarker("Align to right edge minus half");
  2065. ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
  2066. ImGui::DragFloat("float##4a", &f);
  2067. if (show_indented_items)
  2068. {
  2069. ImGui::Indent();
  2070. ImGui::DragFloat("float (indented)##4b", &f);
  2071. ImGui::Unindent();
  2072. }
  2073. ImGui::PopItemWidth();
  2074. // Demonstrate using PushItemWidth to surround three items.
  2075. // Calling SetNextItemWidth() before each of them would have the same effect.
  2076. ImGui::Text("SetNextItemWidth/PushItemWidth(-FLT_MIN)");
  2077. ImGui::SameLine(); HelpMarker("Align to right edge");
  2078. ImGui::PushItemWidth(-FLT_MIN);
  2079. ImGui::DragFloat("##float5a", &f);
  2080. if (show_indented_items)
  2081. {
  2082. ImGui::Indent();
  2083. ImGui::DragFloat("float (indented)##5b", &f);
  2084. ImGui::Unindent();
  2085. }
  2086. ImGui::PopItemWidth();
  2087. ImGui::TreePop();
  2088. }
  2089. if (ImGui::TreeNode("Basic Horizontal Layout"))
  2090. {
  2091. ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
  2092. // Text
  2093. ImGui::Text("Two items: Hello"); ImGui::SameLine();
  2094. ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
  2095. // Adjust spacing
  2096. ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
  2097. ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
  2098. // Button
  2099. ImGui::AlignTextToFramePadding();
  2100. ImGui::Text("Normal buttons"); ImGui::SameLine();
  2101. ImGui::Button("Banana"); ImGui::SameLine();
  2102. ImGui::Button("Apple"); ImGui::SameLine();
  2103. ImGui::Button("Corniflower");
  2104. // Button
  2105. ImGui::Text("Small buttons"); ImGui::SameLine();
  2106. ImGui::SmallButton("Like this one"); ImGui::SameLine();
  2107. ImGui::Text("can fit within a text block.");
  2108. // Aligned to arbitrary position. Easy/cheap column.
  2109. ImGui::Text("Aligned");
  2110. ImGui::SameLine(150); ImGui::Text("x=150");
  2111. ImGui::SameLine(300); ImGui::Text("x=300");
  2112. ImGui::Text("Aligned");
  2113. ImGui::SameLine(150); ImGui::SmallButton("x=150");
  2114. ImGui::SameLine(300); ImGui::SmallButton("x=300");
  2115. // Checkbox
  2116. static bool c1 = false, c2 = false, c3 = false, c4 = false;
  2117. ImGui::Checkbox("My", &c1); ImGui::SameLine();
  2118. ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
  2119. ImGui::Checkbox("Is", &c3); ImGui::SameLine();
  2120. ImGui::Checkbox("Rich", &c4);
  2121. // Various
  2122. static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
  2123. ImGui::PushItemWidth(80);
  2124. const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
  2125. static int item = -1;
  2126. ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
  2127. ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
  2128. ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
  2129. ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
  2130. ImGui::PopItemWidth();
  2131. ImGui::PushItemWidth(80);
  2132. ImGui::Text("Lists:");
  2133. static int selection[4] = { 0, 1, 2, 3 };
  2134. for (int i = 0; i < 4; i++)
  2135. {
  2136. if (i > 0) ImGui::SameLine();
  2137. ImGui::PushID(i);
  2138. ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
  2139. ImGui::PopID();
  2140. //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
  2141. }
  2142. ImGui::PopItemWidth();
  2143. // Dummy
  2144. ImVec2 button_sz(40, 40);
  2145. ImGui::Button("A", button_sz); ImGui::SameLine();
  2146. ImGui::Dummy(button_sz); ImGui::SameLine();
  2147. ImGui::Button("B", button_sz);
  2148. // Manually wrapping
  2149. // (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
  2150. ImGui::Text("Manually wrapping:");
  2151. ImGuiStyle& style = ImGui::GetStyle();
  2152. int buttons_count = 20;
  2153. float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
  2154. for (int n = 0; n < buttons_count; n++)
  2155. {
  2156. ImGui::PushID(n);
  2157. ImGui::Button("Box", button_sz);
  2158. float last_button_x2 = ImGui::GetItemRectMax().x;
  2159. float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
  2160. if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
  2161. ImGui::SameLine();
  2162. ImGui::PopID();
  2163. }
  2164. ImGui::TreePop();
  2165. }
  2166. if (ImGui::TreeNode("Tabs"))
  2167. {
  2168. if (ImGui::TreeNode("Basic"))
  2169. {
  2170. ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
  2171. if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
  2172. {
  2173. if (ImGui::BeginTabItem("Avocado"))
  2174. {
  2175. ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
  2176. ImGui::EndTabItem();
  2177. }
  2178. if (ImGui::BeginTabItem("Broccoli"))
  2179. {
  2180. ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
  2181. ImGui::EndTabItem();
  2182. }
  2183. if (ImGui::BeginTabItem("Cucumber"))
  2184. {
  2185. ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
  2186. ImGui::EndTabItem();
  2187. }
  2188. ImGui::EndTabBar();
  2189. }
  2190. ImGui::Separator();
  2191. ImGui::TreePop();
  2192. }
  2193. if (ImGui::TreeNode("Advanced & Close Button"))
  2194. {
  2195. // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
  2196. static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
  2197. ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable);
  2198. ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
  2199. ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
  2200. ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
  2201. if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
  2202. tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
  2203. if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
  2204. tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
  2205. if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
  2206. tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
  2207. // Tab Bar
  2208. const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
  2209. static bool opened[4] = { true, true, true, true }; // Persistent user state
  2210. for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
  2211. {
  2212. if (n > 0) { ImGui::SameLine(); }
  2213. ImGui::Checkbox(names[n], &opened[n]);
  2214. }
  2215. // Passing a bool* to BeginTabItem() is similar to passing one to Begin():
  2216. // the underlying bool will be set to false when the tab is closed.
  2217. if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
  2218. {
  2219. for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
  2220. if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None))
  2221. {
  2222. ImGui::Text("This is the %s tab!", names[n]);
  2223. if (n & 1)
  2224. ImGui::Text("I am an odd tab.");
  2225. ImGui::EndTabItem();
  2226. }
  2227. ImGui::EndTabBar();
  2228. }
  2229. ImGui::Separator();
  2230. ImGui::TreePop();
  2231. }
  2232. if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags"))
  2233. {
  2234. static ImVector<int> active_tabs;
  2235. static int next_tab_id = 0;
  2236. if (next_tab_id == 0) // Initialize with some default tabs
  2237. for (int i = 0; i < 3; i++)
  2238. active_tabs.push_back(next_tab_id++);
  2239. // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together.
  2240. // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags...
  2241. // but they tend to make more sense together)
  2242. static bool show_leading_button = true;
  2243. static bool show_trailing_button = true;
  2244. ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button);
  2245. ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button);
  2246. // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs
  2247. static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown;
  2248. ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
  2249. if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
  2250. tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
  2251. if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
  2252. tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
  2253. if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
  2254. {
  2255. // Demo a Leading TabItemButton(): click the "?" button to open a menu
  2256. if (show_leading_button)
  2257. if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip))
  2258. ImGui::OpenPopup("MyHelpMenu");
  2259. if (ImGui::BeginPopup("MyHelpMenu"))
  2260. {
  2261. ImGui::Selectable("Hello!");
  2262. ImGui::EndPopup();
  2263. }
  2264. // Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+")
  2265. // Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
  2266. if (show_trailing_button)
  2267. if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip))
  2268. active_tabs.push_back(next_tab_id++); // Add new tab
  2269. // Submit our regular tabs
  2270. for (int n = 0; n < active_tabs.Size; )
  2271. {
  2272. bool open = true;
  2273. char name[16];
  2274. snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]);
  2275. if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None))
  2276. {
  2277. ImGui::Text("This is the %s tab!", name);
  2278. ImGui::EndTabItem();
  2279. }
  2280. if (!open)
  2281. active_tabs.erase(active_tabs.Data + n);
  2282. else
  2283. n++;
  2284. }
  2285. ImGui::EndTabBar();
  2286. }
  2287. ImGui::Separator();
  2288. ImGui::TreePop();
  2289. }
  2290. ImGui::TreePop();
  2291. }
  2292. if (ImGui::TreeNode("Groups"))
  2293. {
  2294. HelpMarker(
  2295. "BeginGroup() basically locks the horizontal position for new line. "
  2296. "EndGroup() bundles the whole group so that you can use \"item\" functions such as "
  2297. "IsItemHovered()/IsItemActive() or SameLine() etc. on the whole group.");
  2298. ImGui::BeginGroup();
  2299. {
  2300. ImGui::BeginGroup();
  2301. ImGui::Button("AAA");
  2302. ImGui::SameLine();
  2303. ImGui::Button("BBB");
  2304. ImGui::SameLine();
  2305. ImGui::BeginGroup();
  2306. ImGui::Button("CCC");
  2307. ImGui::Button("DDD");
  2308. ImGui::EndGroup();
  2309. ImGui::SameLine();
  2310. ImGui::Button("EEE");
  2311. ImGui::EndGroup();
  2312. if (ImGui::IsItemHovered())
  2313. ImGui::SetTooltip("First group hovered");
  2314. }
  2315. // Capture the group size and create widgets using the same size
  2316. ImVec2 size = ImGui::GetItemRectSize();
  2317. const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
  2318. ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
  2319. ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
  2320. ImGui::SameLine();
  2321. ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
  2322. ImGui::EndGroup();
  2323. ImGui::SameLine();
  2324. ImGui::Button("LEVERAGE\nBUZZWORD", size);
  2325. ImGui::SameLine();
  2326. if (ImGui::ListBoxHeader("List", size))
  2327. {
  2328. ImGui::Selectable("Selected", true);
  2329. ImGui::Selectable("Not Selected", false);
  2330. ImGui::ListBoxFooter();
  2331. }
  2332. ImGui::TreePop();
  2333. }
  2334. if (ImGui::TreeNode("Text Baseline Alignment"))
  2335. {
  2336. {
  2337. ImGui::BulletText("Text baseline:");
  2338. ImGui::SameLine(); HelpMarker(
  2339. "This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. "
  2340. "Lines only composed of text or \"small\" widgets use less vertical space than lines with framed widgets.");
  2341. ImGui::Indent();
  2342. ImGui::Text("KO Blahblah"); ImGui::SameLine();
  2343. ImGui::Button("Some framed item"); ImGui::SameLine();
  2344. HelpMarker("Baseline of button will look misaligned with text..");
  2345. // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
  2346. // (because we don't know what's coming after the Text() statement, we need to move the text baseline
  2347. // down by FramePadding.y ahead of time)
  2348. ImGui::AlignTextToFramePadding();
  2349. ImGui::Text("OK Blahblah"); ImGui::SameLine();
  2350. ImGui::Button("Some framed item"); ImGui::SameLine();
  2351. HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y");
  2352. // SmallButton() uses the same vertical padding as Text
  2353. ImGui::Button("TEST##1"); ImGui::SameLine();
  2354. ImGui::Text("TEST"); ImGui::SameLine();
  2355. ImGui::SmallButton("TEST##2");
  2356. // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
  2357. ImGui::AlignTextToFramePadding();
  2358. ImGui::Text("Text aligned to framed item"); ImGui::SameLine();
  2359. ImGui::Button("Item##1"); ImGui::SameLine();
  2360. ImGui::Text("Item"); ImGui::SameLine();
  2361. ImGui::SmallButton("Item##2"); ImGui::SameLine();
  2362. ImGui::Button("Item##3");
  2363. ImGui::Unindent();
  2364. }
  2365. ImGui::Spacing();
  2366. {
  2367. ImGui::BulletText("Multi-line text:");
  2368. ImGui::Indent();
  2369. ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
  2370. ImGui::Text("Hello\nWorld"); ImGui::SameLine();
  2371. ImGui::Text("Banana");
  2372. ImGui::Text("Banana"); ImGui::SameLine();
  2373. ImGui::Text("Hello\nWorld"); ImGui::SameLine();
  2374. ImGui::Text("One\nTwo\nThree");
  2375. ImGui::Button("HOP##1"); ImGui::SameLine();
  2376. ImGui::Text("Banana"); ImGui::SameLine();
  2377. ImGui::Text("Hello\nWorld"); ImGui::SameLine();
  2378. ImGui::Text("Banana");
  2379. ImGui::Button("HOP##2"); ImGui::SameLine();
  2380. ImGui::Text("Hello\nWorld"); ImGui::SameLine();
  2381. ImGui::Text("Banana");
  2382. ImGui::Unindent();
  2383. }
  2384. ImGui::Spacing();
  2385. {
  2386. ImGui::BulletText("Misc items:");
  2387. ImGui::Indent();
  2388. // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button.
  2389. ImGui::Button("80x80", ImVec2(80, 80));
  2390. ImGui::SameLine();
  2391. ImGui::Button("50x50", ImVec2(50, 50));
  2392. ImGui::SameLine();
  2393. ImGui::Button("Button()");
  2394. ImGui::SameLine();
  2395. ImGui::SmallButton("SmallButton()");
  2396. // Tree
  2397. const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
  2398. ImGui::Button("Button##1");
  2399. ImGui::SameLine(0.0f, spacing);
  2400. if (ImGui::TreeNode("Node##1"))
  2401. {
  2402. // Placeholder tree data
  2403. for (int i = 0; i < 6; i++)
  2404. ImGui::BulletText("Item %d..", i);
  2405. ImGui::TreePop();
  2406. }
  2407. // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget.
  2408. // Otherwise you can use SmallButton() (smaller fit).
  2409. ImGui::AlignTextToFramePadding();
  2410. // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add
  2411. // other contents below the node.
  2412. bool node_open = ImGui::TreeNode("Node##2");
  2413. ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
  2414. if (node_open)
  2415. {
  2416. // Placeholder tree data
  2417. for (int i = 0; i < 6; i++)
  2418. ImGui::BulletText("Item %d..", i);
  2419. ImGui::TreePop();
  2420. }
  2421. // Bullet
  2422. ImGui::Button("Button##3");
  2423. ImGui::SameLine(0.0f, spacing);
  2424. ImGui::BulletText("Bullet text");
  2425. ImGui::AlignTextToFramePadding();
  2426. ImGui::BulletText("Node");
  2427. ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
  2428. ImGui::Unindent();
  2429. }
  2430. ImGui::TreePop();
  2431. }
  2432. if (ImGui::TreeNode("Scrolling"))
  2433. {
  2434. // Vertical scroll functions
  2435. HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position.");
  2436. static int track_item = 50;
  2437. static bool enable_track = true;
  2438. static bool enable_extra_decorations = false;
  2439. static float scroll_to_off_px = 0.0f;
  2440. static float scroll_to_pos_px = 200.0f;
  2441. ImGui::Checkbox("Decoration", &enable_extra_decorations);
  2442. ImGui::Checkbox("Track", &enable_track);
  2443. ImGui::PushItemWidth(100);
  2444. ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
  2445. bool scroll_to_off = ImGui::Button("Scroll Offset");
  2446. ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
  2447. bool scroll_to_pos = ImGui::Button("Scroll To Pos");
  2448. ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
  2449. ImGui::PopItemWidth();
  2450. if (scroll_to_off || scroll_to_pos)
  2451. enable_track = false;
  2452. ImGuiStyle& style = ImGui::GetStyle();
  2453. float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5;
  2454. if (child_w < 1.0f)
  2455. child_w = 1.0f;
  2456. ImGui::PushID("##VerticalScrolling");
  2457. for (int i = 0; i < 5; i++)
  2458. {
  2459. if (i > 0) ImGui::SameLine();
  2460. ImGui::BeginGroup();
  2461. const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" };
  2462. ImGui::TextUnformatted(names[i]);
  2463. const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0;
  2464. const ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
  2465. const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), true, child_flags);
  2466. if (ImGui::BeginMenuBar())
  2467. {
  2468. ImGui::TextUnformatted("abc");
  2469. ImGui::EndMenuBar();
  2470. }
  2471. if (scroll_to_off)
  2472. ImGui::SetScrollY(scroll_to_off_px);
  2473. if (scroll_to_pos)
  2474. ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
  2475. if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
  2476. {
  2477. for (int item = 0; item < 100; item++)
  2478. {
  2479. if (enable_track && item == track_item)
  2480. {
  2481. ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
  2482. ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
  2483. }
  2484. else
  2485. {
  2486. ImGui::Text("Item %d", item);
  2487. }
  2488. }
  2489. }
  2490. float scroll_y = ImGui::GetScrollY();
  2491. float scroll_max_y = ImGui::GetScrollMaxY();
  2492. ImGui::EndChild();
  2493. ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
  2494. ImGui::EndGroup();
  2495. }
  2496. ImGui::PopID();
  2497. // Horizontal scroll functions
  2498. ImGui::Spacing();
  2499. HelpMarker(
  2500. "Use SetScrollHereX() or SetScrollFromPosX() to scroll to a given horizontal position.\n\n"
  2501. "Because the clipping rectangle of most window hides half worth of WindowPadding on the "
  2502. "left/right, using SetScrollFromPosX(+1) will usually result in clipped text whereas the "
  2503. "equivalent SetScrollFromPosY(+1) wouldn't.");
  2504. ImGui::PushID("##HorizontalScrolling");
  2505. for (int i = 0; i < 5; i++)
  2506. {
  2507. float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f;
  2508. ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0);
  2509. ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
  2510. bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), true, child_flags);
  2511. if (scroll_to_off)
  2512. ImGui::SetScrollX(scroll_to_off_px);
  2513. if (scroll_to_pos)
  2514. ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f);
  2515. if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
  2516. {
  2517. for (int item = 0; item < 100; item++)
  2518. {
  2519. if (enable_track && item == track_item)
  2520. {
  2521. ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
  2522. ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right
  2523. }
  2524. else
  2525. {
  2526. ImGui::Text("Item %d", item);
  2527. }
  2528. ImGui::SameLine();
  2529. }
  2530. }
  2531. float scroll_x = ImGui::GetScrollX();
  2532. float scroll_max_x = ImGui::GetScrollMaxX();
  2533. ImGui::EndChild();
  2534. ImGui::SameLine();
  2535. const char* names[] = { "Left", "25%", "Center", "75%", "Right" };
  2536. ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x);
  2537. ImGui::Spacing();
  2538. }
  2539. ImGui::PopID();
  2540. // Miscellaneous Horizontal Scrolling Demo
  2541. HelpMarker(
  2542. "Horizontal scrolling for a window is enabled via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\n"
  2543. "You may want to also explicitly specify content width by using SetNextWindowContentWidth() before Begin().");
  2544. static int lines = 7;
  2545. ImGui::SliderInt("Lines", &lines, 1, 15);
  2546. ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
  2547. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
  2548. ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30);
  2549. ImGui::BeginChild("scrolling", scrolling_child_size, true, ImGuiWindowFlags_HorizontalScrollbar);
  2550. for (int line = 0; line < lines; line++)
  2551. {
  2552. // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine()
  2553. // If you want to create your own time line for a real application you may be better off manipulating
  2554. // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
  2555. // yourself. You may also want to use the lower-level ImDrawList API.
  2556. int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
  2557. for (int n = 0; n < num_buttons; n++)
  2558. {
  2559. if (n > 0) ImGui::SameLine();
  2560. ImGui::PushID(n + line * 1000);
  2561. char num_buf[16];
  2562. sprintf(num_buf, "%d", n);
  2563. const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
  2564. float hue = n * 0.05f;
  2565. ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
  2566. ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
  2567. ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
  2568. ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
  2569. ImGui::PopStyleColor(3);
  2570. ImGui::PopID();
  2571. }
  2572. }
  2573. float scroll_x = ImGui::GetScrollX();
  2574. float scroll_max_x = ImGui::GetScrollMaxX();
  2575. ImGui::EndChild();
  2576. ImGui::PopStyleVar(2);
  2577. float scroll_x_delta = 0.0f;
  2578. ImGui::SmallButton("<<");
  2579. if (ImGui::IsItemActive())
  2580. scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f;
  2581. ImGui::SameLine();
  2582. ImGui::Text("Scroll from code"); ImGui::SameLine();
  2583. ImGui::SmallButton(">>");
  2584. if (ImGui::IsItemActive())
  2585. scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f;
  2586. ImGui::SameLine();
  2587. ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
  2588. if (scroll_x_delta != 0.0f)
  2589. {
  2590. // Demonstrate a trick: you can use Begin to set yourself in the context of another window
  2591. // (here we are already out of your child window)
  2592. ImGui::BeginChild("scrolling");
  2593. ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
  2594. ImGui::EndChild();
  2595. }
  2596. ImGui::Spacing();
  2597. static bool show_horizontal_contents_size_demo_window = false;
  2598. ImGui::Checkbox("Show Horizontal contents size demo window", &show_horizontal_contents_size_demo_window);
  2599. if (show_horizontal_contents_size_demo_window)
  2600. {
  2601. static bool show_h_scrollbar = true;
  2602. static bool show_button = true;
  2603. static bool show_tree_nodes = true;
  2604. static bool show_text_wrapped = false;
  2605. static bool show_columns = true;
  2606. static bool show_tab_bar = true;
  2607. static bool show_child = false;
  2608. static bool explicit_content_size = false;
  2609. static float contents_size_x = 300.0f;
  2610. if (explicit_content_size)
  2611. ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
  2612. ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
  2613. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
  2614. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
  2615. HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
  2616. ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
  2617. ImGui::Checkbox("Button", &show_button); // Will grow contents size (unless explicitly overwritten)
  2618. ImGui::Checkbox("Tree nodes", &show_tree_nodes); // Will grow contents size and display highlight over full width
  2619. ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
  2620. ImGui::Checkbox("Columns", &show_columns); // Will use contents size
  2621. ImGui::Checkbox("Tab bar", &show_tab_bar); // Will use contents size
  2622. ImGui::Checkbox("Child", &show_child); // Will grow and use contents size
  2623. ImGui::Checkbox("Explicit content size", &explicit_content_size);
  2624. ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
  2625. if (explicit_content_size)
  2626. {
  2627. ImGui::SameLine();
  2628. ImGui::SetNextItemWidth(100);
  2629. ImGui::DragFloat("##csx", &contents_size_x);
  2630. ImVec2 p = ImGui::GetCursorScreenPos();
  2631. ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
  2632. ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
  2633. ImGui::Dummy(ImVec2(0, 10));
  2634. }
  2635. ImGui::PopStyleVar(2);
  2636. ImGui::Separator();
  2637. if (show_button)
  2638. {
  2639. ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
  2640. }
  2641. if (show_tree_nodes)
  2642. {
  2643. bool open = true;
  2644. if (ImGui::TreeNode("this is a tree node"))
  2645. {
  2646. if (ImGui::TreeNode("another one of those tree node..."))
  2647. {
  2648. ImGui::Text("Some tree contents");
  2649. ImGui::TreePop();
  2650. }
  2651. ImGui::TreePop();
  2652. }
  2653. ImGui::CollapsingHeader("CollapsingHeader", &open);
  2654. }
  2655. if (show_text_wrapped)
  2656. {
  2657. ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
  2658. }
  2659. if (show_columns)
  2660. {
  2661. ImGui::Columns(4);
  2662. for (int n = 0; n < 4; n++)
  2663. {
  2664. ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
  2665. ImGui::NextColumn();
  2666. }
  2667. ImGui::Columns(1);
  2668. }
  2669. if (show_tab_bar && ImGui::BeginTabBar("Hello"))
  2670. {
  2671. if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
  2672. if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
  2673. if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
  2674. if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
  2675. ImGui::EndTabBar();
  2676. }
  2677. if (show_child)
  2678. {
  2679. ImGui::BeginChild("child", ImVec2(0, 0), true);
  2680. ImGui::EndChild();
  2681. }
  2682. ImGui::End();
  2683. }
  2684. ImGui::TreePop();
  2685. }
  2686. if (ImGui::TreeNode("Clipping"))
  2687. {
  2688. static ImVec2 size(100.0f, 100.0f);
  2689. static ImVec2 offset(30.0f, 30.0f);
  2690. ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
  2691. ImGui::TextWrapped("(Click and drag to scroll)");
  2692. for (int n = 0; n < 3; n++)
  2693. {
  2694. if (n > 0)
  2695. ImGui::SameLine();
  2696. ImGui::PushID(n);
  2697. ImGui::BeginGroup(); // Lock X position
  2698. ImGui::InvisibleButton("##empty", size);
  2699. if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
  2700. {
  2701. offset.x += ImGui::GetIO().MouseDelta.x;
  2702. offset.y += ImGui::GetIO().MouseDelta.y;
  2703. }
  2704. const ImVec2 p0 = ImGui::GetItemRectMin();
  2705. const ImVec2 p1 = ImGui::GetItemRectMax();
  2706. const char* text_str = "Line 1 hello\nLine 2 clip me!";
  2707. const ImVec2 text_pos = ImVec2(p0.x + offset.x, p0.y + offset.y);
  2708. ImDrawList* draw_list = ImGui::GetWindowDrawList();
  2709. switch (n)
  2710. {
  2711. case 0:
  2712. HelpMarker(
  2713. "Using ImGui::PushClipRect():\n"
  2714. "Will alter ImGui hit-testing logic + ImDrawList rendering.\n"
  2715. "(use this if you want your clipping rectangle to affect interactions)");
  2716. ImGui::PushClipRect(p0, p1, true);
  2717. draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
  2718. draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
  2719. ImGui::PopClipRect();
  2720. break;
  2721. case 1:
  2722. HelpMarker(
  2723. "Using ImDrawList::PushClipRect():\n"
  2724. "Will alter ImDrawList rendering only.\n"
  2725. "(use this as a shortcut if you are only using ImDrawList calls)");
  2726. draw_list->PushClipRect(p0, p1, true);
  2727. draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
  2728. draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
  2729. draw_list->PopClipRect();
  2730. break;
  2731. case 2:
  2732. HelpMarker(
  2733. "Using ImDrawList::AddText() with a fine ClipRect:\n"
  2734. "Will alter only this specific ImDrawList::AddText() rendering.\n"
  2735. "(this is often used internally to avoid altering the clipping rectangle and minimize draw calls)");
  2736. ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert.
  2737. draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
  2738. draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect);
  2739. break;
  2740. }
  2741. ImGui::EndGroup();
  2742. ImGui::PopID();
  2743. }
  2744. ImGui::TreePop();
  2745. }
  2746. }
  2747. static void ShowDemoWindowPopups()
  2748. {
  2749. if (!ImGui::CollapsingHeader("Popups & Modal windows"))
  2750. return;
  2751. // The properties of popups windows are:
  2752. // - They block normal mouse hovering detection outside them. (*)
  2753. // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
  2754. // - Their visibility state (~bool) is held internally by Dear ImGui instead of being held by the programmer as
  2755. // we are used to with regular Begin() calls. User can manipulate the visibility state by calling OpenPopup().
  2756. // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even
  2757. // when normally blocked by a popup.
  2758. // Those three properties are connected. The library needs to hold their visibility state BECAUSE it can close
  2759. // popups at any time.
  2760. // Typical use for regular windows:
  2761. // bool my_tool_is_active = false; if (ImGui::Button("Open")) my_tool_is_active = true; [...] if (my_tool_is_active) Begin("My Tool", &my_tool_is_active) { [...] } End();
  2762. // Typical use for popups:
  2763. // if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
  2764. // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
  2765. // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
  2766. if (ImGui::TreeNode("Popups"))
  2767. {
  2768. ImGui::TextWrapped(
  2769. "When a popup is active, it inhibits interacting with windows that are behind the popup. "
  2770. "Clicking outside the popup closes it.");
  2771. static int selected_fish = -1;
  2772. const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
  2773. static bool toggles[] = { true, false, false, false, false };
  2774. // Simple selection popup (if you want to show the current selection inside the Button itself,
  2775. // you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
  2776. if (ImGui::Button("Select.."))
  2777. ImGui::OpenPopup("my_select_popup");
  2778. ImGui::SameLine();
  2779. ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
  2780. if (ImGui::BeginPopup("my_select_popup"))
  2781. {
  2782. ImGui::Text("Aquarium");
  2783. ImGui::Separator();
  2784. for (int i = 0; i < IM_ARRAYSIZE(names); i++)
  2785. if (ImGui::Selectable(names[i]))
  2786. selected_fish = i;
  2787. ImGui::EndPopup();
  2788. }
  2789. // Showing a menu with toggles
  2790. if (ImGui::Button("Toggle.."))
  2791. ImGui::OpenPopup("my_toggle_popup");
  2792. if (ImGui::BeginPopup("my_toggle_popup"))
  2793. {
  2794. for (int i = 0; i < IM_ARRAYSIZE(names); i++)
  2795. ImGui::MenuItem(names[i], "", &toggles[i]);
  2796. if (ImGui::BeginMenu("Sub-menu"))
  2797. {
  2798. ImGui::MenuItem("Click me");
  2799. ImGui::EndMenu();
  2800. }
  2801. ImGui::Separator();
  2802. ImGui::Text("Tooltip here");
  2803. if (ImGui::IsItemHovered())
  2804. ImGui::SetTooltip("I am a tooltip over a popup");
  2805. if (ImGui::Button("Stacked Popup"))
  2806. ImGui::OpenPopup("another popup");
  2807. if (ImGui::BeginPopup("another popup"))
  2808. {
  2809. for (int i = 0; i < IM_ARRAYSIZE(names); i++)
  2810. ImGui::MenuItem(names[i], "", &toggles[i]);
  2811. if (ImGui::BeginMenu("Sub-menu"))
  2812. {
  2813. ImGui::MenuItem("Click me");
  2814. if (ImGui::Button("Stacked Popup"))
  2815. ImGui::OpenPopup("another popup");
  2816. if (ImGui::BeginPopup("another popup"))
  2817. {
  2818. ImGui::Text("I am the last one here.");
  2819. ImGui::EndPopup();
  2820. }
  2821. ImGui::EndMenu();
  2822. }
  2823. ImGui::EndPopup();
  2824. }
  2825. ImGui::EndPopup();
  2826. }
  2827. // Call the more complete ShowExampleMenuFile which we use in various places of this demo
  2828. if (ImGui::Button("File Menu.."))
  2829. ImGui::OpenPopup("my_file_popup");
  2830. if (ImGui::BeginPopup("my_file_popup"))
  2831. {
  2832. ShowExampleMenuFile();
  2833. ImGui::EndPopup();
  2834. }
  2835. ImGui::TreePop();
  2836. }
  2837. if (ImGui::TreeNode("Context menus"))
  2838. {
  2839. // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
  2840. // if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
  2841. // OpenPopup(id);
  2842. // return BeginPopup(id);
  2843. // For more advanced uses you may want to replicate and customize this code.
  2844. // See details in BeginPopupContextItem().
  2845. static float value = 0.5f;
  2846. ImGui::Text("Value = %.3f (<-- right-click here)", value);
  2847. if (ImGui::BeginPopupContextItem("item context menu"))
  2848. {
  2849. if (ImGui::Selectable("Set to zero")) value = 0.0f;
  2850. if (ImGui::Selectable("Set to PI")) value = 3.1415f;
  2851. ImGui::SetNextItemWidth(-1);
  2852. ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
  2853. ImGui::EndPopup();
  2854. }
  2855. // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the
  2856. // Begin() call. So here we will make it that clicking on the text field with the right mouse button (1)
  2857. // will toggle the visibility of the popup above.
  2858. ImGui::Text("(You can also right-click me to open the same popup as above.)");
  2859. ImGui::OpenPopupOnItemClick("item context menu", 1);
  2860. // When used after an item that has an ID (e.g.Button), we can skip providing an ID to BeginPopupContextItem().
  2861. // BeginPopupContextItem() will use the last item ID as the popup ID.
  2862. // In addition here, we want to include your editable label inside the button label.
  2863. // We use the ### operator to override the ID (read FAQ about ID for details)
  2864. static char name[32] = "Label1";
  2865. char buf[64];
  2866. sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
  2867. ImGui::Button(buf);
  2868. if (ImGui::BeginPopupContextItem())
  2869. {
  2870. ImGui::Text("Edit name:");
  2871. ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
  2872. if (ImGui::Button("Close"))
  2873. ImGui::CloseCurrentPopup();
  2874. ImGui::EndPopup();
  2875. }
  2876. ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
  2877. ImGui::TreePop();
  2878. }
  2879. if (ImGui::TreeNode("Modals"))
  2880. {
  2881. ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside.");
  2882. if (ImGui::Button("Delete.."))
  2883. ImGui::OpenPopup("Delete?");
  2884. // Always center this window when appearing
  2885. ImVec2 center = ImGui::GetMainViewport()->GetCenter();
  2886. //ImVec2 parent_pos = ImGui::GetWindowPos();
  2887. //ImVec2 parent_size = ImGui::GetWindowSize();
  2888. //ImVec2 center(parent_pos.x + parent_size.x * 0.5f, parent_pos.y + parent_size.y * 0.5f);
  2889. ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  2890. if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
  2891. {
  2892. ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
  2893. ImGui::Separator();
  2894. //static int unused_i = 0;
  2895. //ImGui::Combo("Combo", &unused_i, "Delete\0Delete harder\0");
  2896. static bool dont_ask_me_next_time = false;
  2897. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
  2898. ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
  2899. ImGui::PopStyleVar();
  2900. if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
  2901. ImGui::SetItemDefaultFocus();
  2902. ImGui::SameLine();
  2903. if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
  2904. ImGui::EndPopup();
  2905. }
  2906. if (ImGui::Button("Stacked modals.."))
  2907. ImGui::OpenPopup("Stacked 1");
  2908. if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar))
  2909. {
  2910. if (ImGui::BeginMenuBar())
  2911. {
  2912. if (ImGui::BeginMenu("File"))
  2913. {
  2914. if (ImGui::MenuItem("Some menu item")) {}
  2915. ImGui::EndMenu();
  2916. }
  2917. ImGui::EndMenuBar();
  2918. }
  2919. ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
  2920. // Testing behavior of widgets stacking their own regular popups over the modal.
  2921. static int item = 1;
  2922. static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
  2923. ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
  2924. ImGui::ColorEdit4("color", color);
  2925. if (ImGui::Button("Add another modal.."))
  2926. ImGui::OpenPopup("Stacked 2");
  2927. // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which
  2928. // will close the popup. Note that the visibility state of popups is owned by imgui, so the input value
  2929. // of the bool actually doesn't matter here.
  2930. bool unused_open = true;
  2931. if (ImGui::BeginPopupModal("Stacked 2", &unused_open))
  2932. {
  2933. ImGui::Text("Hello from Stacked The Second!");
  2934. if (ImGui::Button("Close"))
  2935. ImGui::CloseCurrentPopup();
  2936. ImGui::EndPopup();
  2937. }
  2938. if (ImGui::Button("Close"))
  2939. ImGui::CloseCurrentPopup();
  2940. ImGui::EndPopup();
  2941. }
  2942. ImGui::TreePop();
  2943. }
  2944. if (ImGui::TreeNode("Menus inside a regular window"))
  2945. {
  2946. ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
  2947. ImGui::Separator();
  2948. // Note: As a quirk in this very specific example, we want to differentiate the parent of this menu from the
  2949. // parent of the various popup menus above. To do so we are encloding the items in a PushID()/PopID() block
  2950. // to make them two different menusets. If we don't, opening any popup above and hovering our menu here would
  2951. // open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it,
  2952. // which is the desired behavior for regular menus.
  2953. ImGui::PushID("foo");
  2954. ImGui::MenuItem("Menu item", "CTRL+M");
  2955. if (ImGui::BeginMenu("Menu inside a regular window"))
  2956. {
  2957. ShowExampleMenuFile();
  2958. ImGui::EndMenu();
  2959. }
  2960. ImGui::PopID();
  2961. ImGui::Separator();
  2962. ImGui::TreePop();
  2963. }
  2964. }
  2965. static void ShowDemoWindowColumns()
  2966. {
  2967. if (!ImGui::CollapsingHeader("Columns"))
  2968. return;
  2969. ImGui::PushID("Columns");
  2970. static bool disable_indent = false;
  2971. ImGui::Checkbox("Disable tree indentation", &disable_indent);
  2972. ImGui::SameLine();
  2973. HelpMarker("Disable the indenting of tree nodes so demo columns can use the full window width.");
  2974. if (disable_indent)
  2975. ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
  2976. // Basic columns
  2977. if (ImGui::TreeNode("Basic"))
  2978. {
  2979. ImGui::Text("Without border:");
  2980. ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border
  2981. ImGui::Separator();
  2982. for (int n = 0; n < 14; n++)
  2983. {
  2984. char label[32];
  2985. sprintf(label, "Item %d", n);
  2986. if (ImGui::Selectable(label)) {}
  2987. //if (ImGui::Button(label, ImVec2(-FLT_MIN,0.0f))) {}
  2988. ImGui::NextColumn();
  2989. }
  2990. ImGui::Columns(1);
  2991. ImGui::Separator();
  2992. ImGui::Text("With border:");
  2993. ImGui::Columns(4, "mycolumns"); // 4-ways, with border
  2994. ImGui::Separator();
  2995. ImGui::Text("ID"); ImGui::NextColumn();
  2996. ImGui::Text("Name"); ImGui::NextColumn();
  2997. ImGui::Text("Path"); ImGui::NextColumn();
  2998. ImGui::Text("Hovered"); ImGui::NextColumn();
  2999. ImGui::Separator();
  3000. const char* names[3] = { "One", "Two", "Three" };
  3001. const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
  3002. static int selected = -1;
  3003. for (int i = 0; i < 3; i++)
  3004. {
  3005. char label[32];
  3006. sprintf(label, "%04d", i);
  3007. if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
  3008. selected = i;
  3009. bool hovered = ImGui::IsItemHovered();
  3010. ImGui::NextColumn();
  3011. ImGui::Text(names[i]); ImGui::NextColumn();
  3012. ImGui::Text(paths[i]); ImGui::NextColumn();
  3013. ImGui::Text("%d", hovered); ImGui::NextColumn();
  3014. }
  3015. ImGui::Columns(1);
  3016. ImGui::Separator();
  3017. ImGui::TreePop();
  3018. }
  3019. if (ImGui::TreeNode("Borders"))
  3020. {
  3021. // NB: Future columns API should allow automatic horizontal borders.
  3022. static bool h_borders = true;
  3023. static bool v_borders = true;
  3024. static int columns_count = 4;
  3025. const int lines_count = 3;
  3026. ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
  3027. ImGui::DragInt("##columns_count", &columns_count, 0.1f, 2, 10, "%d columns");
  3028. if (columns_count < 2)
  3029. columns_count = 2;
  3030. ImGui::SameLine();
  3031. ImGui::Checkbox("horizontal", &h_borders);
  3032. ImGui::SameLine();
  3033. ImGui::Checkbox("vertical", &v_borders);
  3034. ImGui::Columns(columns_count, NULL, v_borders);
  3035. for (int i = 0; i < columns_count * lines_count; i++)
  3036. {
  3037. if (h_borders && ImGui::GetColumnIndex() == 0)
  3038. ImGui::Separator();
  3039. ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i);
  3040. ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
  3041. ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
  3042. ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
  3043. ImGui::Text("Long text that is likely to clip");
  3044. ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f));
  3045. ImGui::NextColumn();
  3046. }
  3047. ImGui::Columns(1);
  3048. if (h_borders)
  3049. ImGui::Separator();
  3050. ImGui::TreePop();
  3051. }
  3052. // Create multiple items in a same cell before switching to next column
  3053. if (ImGui::TreeNode("Mixed items"))
  3054. {
  3055. ImGui::Columns(3, "mixed");
  3056. ImGui::Separator();
  3057. ImGui::Text("Hello");
  3058. ImGui::Button("Banana");
  3059. ImGui::NextColumn();
  3060. ImGui::Text("ImGui");
  3061. ImGui::Button("Apple");
  3062. static float foo = 1.0f;
  3063. ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
  3064. ImGui::Text("An extra line here.");
  3065. ImGui::NextColumn();
  3066. ImGui::Text("Sailor");
  3067. ImGui::Button("Corniflower");
  3068. static float bar = 1.0f;
  3069. ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
  3070. ImGui::NextColumn();
  3071. if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
  3072. if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
  3073. if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
  3074. ImGui::Columns(1);
  3075. ImGui::Separator();
  3076. ImGui::TreePop();
  3077. }
  3078. // Word wrapping
  3079. if (ImGui::TreeNode("Word-wrapping"))
  3080. {
  3081. ImGui::Columns(2, "word-wrapping");
  3082. ImGui::Separator();
  3083. ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
  3084. ImGui::TextWrapped("Hello Left");
  3085. ImGui::NextColumn();
  3086. ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
  3087. ImGui::TextWrapped("Hello Right");
  3088. ImGui::Columns(1);
  3089. ImGui::Separator();
  3090. ImGui::TreePop();
  3091. }
  3092. // Scrolling columns
  3093. /*
  3094. if (ImGui::TreeNode("Vertical Scrolling"))
  3095. {
  3096. ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
  3097. ImGui::Columns(3);
  3098. ImGui::Text("ID"); ImGui::NextColumn();
  3099. ImGui::Text("Name"); ImGui::NextColumn();
  3100. ImGui::Text("Path"); ImGui::NextColumn();
  3101. ImGui::Columns(1);
  3102. ImGui::Separator();
  3103. ImGui::EndChild();
  3104. ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
  3105. ImGui::Columns(3);
  3106. for (int i = 0; i < 10; i++)
  3107. {
  3108. ImGui::Text("%04d", i); ImGui::NextColumn();
  3109. ImGui::Text("Foobar"); ImGui::NextColumn();
  3110. ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
  3111. }
  3112. ImGui::Columns(1);
  3113. ImGui::EndChild();
  3114. ImGui::TreePop();
  3115. }
  3116. */
  3117. if (ImGui::TreeNode("Horizontal Scrolling"))
  3118. {
  3119. ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
  3120. ImVec2 child_size = ImVec2(0, ImGui::GetFontSize() * 20.0f);
  3121. ImGui::BeginChild("##ScrollingRegion", child_size, false, ImGuiWindowFlags_HorizontalScrollbar);
  3122. ImGui::Columns(10);
  3123. int ITEMS_COUNT = 2000;
  3124. ImGuiListClipper clipper; // Also demonstrate using the clipper for large list
  3125. clipper.Begin(ITEMS_COUNT);
  3126. while (clipper.Step())
  3127. {
  3128. for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
  3129. for (int j = 0; j < 10; j++)
  3130. {
  3131. ImGui::Text("Line %d Column %d...", i, j);
  3132. ImGui::NextColumn();
  3133. }
  3134. }
  3135. ImGui::Columns(1);
  3136. ImGui::EndChild();
  3137. ImGui::TreePop();
  3138. }
  3139. if (ImGui::TreeNode("Tree"))
  3140. {
  3141. ImGui::Columns(2, "tree", true);
  3142. for (int x = 0; x < 3; x++)
  3143. {
  3144. bool open1 = ImGui::TreeNode((void*)(intptr_t)x, "Node%d", x);
  3145. ImGui::NextColumn();
  3146. ImGui::Text("Node contents");
  3147. ImGui::NextColumn();
  3148. if (open1)
  3149. {
  3150. for (int y = 0; y < 3; y++)
  3151. {
  3152. bool open2 = ImGui::TreeNode((void*)(intptr_t)y, "Node%d.%d", x, y);
  3153. ImGui::NextColumn();
  3154. ImGui::Text("Node contents");
  3155. if (open2)
  3156. {
  3157. ImGui::Text("Even more contents");
  3158. if (ImGui::TreeNode("Tree in column"))
  3159. {
  3160. ImGui::Text("The quick brown fox jumps over the lazy dog");
  3161. ImGui::TreePop();
  3162. }
  3163. }
  3164. ImGui::NextColumn();
  3165. if (open2)
  3166. ImGui::TreePop();
  3167. }
  3168. ImGui::TreePop();
  3169. }
  3170. }
  3171. ImGui::Columns(1);
  3172. ImGui::TreePop();
  3173. }
  3174. if (disable_indent)
  3175. ImGui::PopStyleVar();
  3176. ImGui::PopID();
  3177. }
  3178. static void ShowDemoWindowMisc()
  3179. {
  3180. if (ImGui::CollapsingHeader("Filtering"))
  3181. {
  3182. // Helper class to easy setup a text filter.
  3183. // You may want to implement a more feature-full filtering scheme in your own application.
  3184. static ImGuiTextFilter filter;
  3185. ImGui::Text("Filter usage:\n"
  3186. " \"\" display all lines\n"
  3187. " \"xxx\" display lines containing \"xxx\"\n"
  3188. " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
  3189. " \"-xxx\" hide lines containing \"xxx\"");
  3190. filter.Draw();
  3191. const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
  3192. for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
  3193. if (filter.PassFilter(lines[i]))
  3194. ImGui::BulletText("%s", lines[i]);
  3195. }
  3196. if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
  3197. {
  3198. ImGuiIO& io = ImGui::GetIO();
  3199. // Display ImGuiIO output flags
  3200. ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
  3201. ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
  3202. ImGui::Text("WantTextInput: %d", io.WantTextInput);
  3203. ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
  3204. ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
  3205. // Display Keyboard/Mouse state
  3206. if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
  3207. {
  3208. if (ImGui::IsMousePosValid())
  3209. ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
  3210. else
  3211. ImGui::Text("Mouse pos: <INVALID>");
  3212. ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
  3213. ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
  3214. ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
  3215. ImGui::Text("Mouse dblclick:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
  3216. ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
  3217. ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
  3218. ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); }
  3219. ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
  3220. ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
  3221. ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
  3222. ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
  3223. ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); }
  3224. ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); }
  3225. ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); }
  3226. ImGui::Button("Hovering me sets the\nkeyboard capture flag");
  3227. if (ImGui::IsItemHovered())
  3228. ImGui::CaptureKeyboardFromApp(true);
  3229. ImGui::SameLine();
  3230. ImGui::Button("Holding me clears the\nthe keyboard capture flag");
  3231. if (ImGui::IsItemActive())
  3232. ImGui::CaptureKeyboardFromApp(false);
  3233. ImGui::TreePop();
  3234. }
  3235. if (ImGui::TreeNode("Tabbing"))
  3236. {
  3237. ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
  3238. static char buf[32] = "hello";
  3239. ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
  3240. ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
  3241. ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
  3242. ImGui::PushAllowKeyboardFocus(false);
  3243. ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
  3244. //ImGui::SameLine(); HelpMarker("Use ImGui::PushAllowKeyboardFocus(bool) to disable tabbing through certain widgets.");
  3245. ImGui::PopAllowKeyboardFocus();
  3246. ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
  3247. ImGui::TreePop();
  3248. }
  3249. if (ImGui::TreeNode("Focus from code"))
  3250. {
  3251. bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
  3252. bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
  3253. bool focus_3 = ImGui::Button("Focus on 3");
  3254. int has_focus = 0;
  3255. static char buf[128] = "click on a button to set focus";
  3256. if (focus_1) ImGui::SetKeyboardFocusHere();
  3257. ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
  3258. if (ImGui::IsItemActive()) has_focus = 1;
  3259. if (focus_2) ImGui::SetKeyboardFocusHere();
  3260. ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
  3261. if (ImGui::IsItemActive()) has_focus = 2;
  3262. ImGui::PushAllowKeyboardFocus(false);
  3263. if (focus_3) ImGui::SetKeyboardFocusHere();
  3264. ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
  3265. if (ImGui::IsItemActive()) has_focus = 3;
  3266. ImGui::PopAllowKeyboardFocus();
  3267. if (has_focus)
  3268. ImGui::Text("Item with focus: %d", has_focus);
  3269. else
  3270. ImGui::Text("Item with focus: <none>");
  3271. // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
  3272. static float f3[3] = { 0.0f, 0.0f, 0.0f };
  3273. int focus_ahead = -1;
  3274. if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine();
  3275. if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine();
  3276. if (ImGui::Button("Focus on Z")) { focus_ahead = 2; }
  3277. if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
  3278. ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
  3279. ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
  3280. ImGui::TreePop();
  3281. }
  3282. if (ImGui::TreeNode("Dragging"))
  3283. {
  3284. ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
  3285. for (int button = 0; button < 3; button++)
  3286. {
  3287. ImGui::Text("IsMouseDragging(%d):", button);
  3288. ImGui::Text(" w/ default threshold: %d,", ImGui::IsMouseDragging(button));
  3289. ImGui::Text(" w/ zero threshold: %d,", ImGui::IsMouseDragging(button, 0.0f));
  3290. ImGui::Text(" w/ large threshold: %d,", ImGui::IsMouseDragging(button, 20.0f));
  3291. }
  3292. ImGui::Button("Drag Me");
  3293. if (ImGui::IsItemActive())
  3294. ImGui::GetForegroundDrawList()->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); // Draw a line between the button and the mouse cursor
  3295. // Drag operations gets "unlocked" when the mouse has moved past a certain threshold
  3296. // (the default threshold is stored in io.MouseDragThreshold). You can request a lower or higher
  3297. // threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta().
  3298. ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
  3299. ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
  3300. ImVec2 mouse_delta = io.MouseDelta;
  3301. ImGui::Text("GetMouseDragDelta(0):");
  3302. ImGui::Text(" w/ default threshold: (%.1f, %.1f)", value_with_lock_threshold.x, value_with_lock_threshold.y);
  3303. ImGui::Text(" w/ zero threshold: (%.1f, %.1f)", value_raw.x, value_raw.y);
  3304. ImGui::Text("io.MouseDelta: (%.1f, %.1f)", mouse_delta.x, mouse_delta.y);
  3305. ImGui::TreePop();
  3306. }
  3307. if (ImGui::TreeNode("Mouse cursors"))
  3308. {
  3309. const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" };
  3310. IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
  3311. ImGuiMouseCursor current = ImGui::GetMouseCursor();
  3312. ImGui::Text("Current mouse cursor = %d: %s", current, mouse_cursors_names[current]);
  3313. ImGui::Text("Hover to see mouse cursors:");
  3314. ImGui::SameLine(); HelpMarker(
  3315. "Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. "
  3316. "If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, "
  3317. "otherwise your backend needs to handle it.");
  3318. for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
  3319. {
  3320. char label[32];
  3321. sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
  3322. ImGui::Bullet(); ImGui::Selectable(label, false);
  3323. if (ImGui::IsItemHovered())
  3324. ImGui::SetMouseCursor(i);
  3325. }
  3326. ImGui::TreePop();
  3327. }
  3328. }
  3329. }
  3330. //-----------------------------------------------------------------------------
  3331. // [SECTION] About Window / ShowAboutWindow()
  3332. // Access from Dear ImGui Demo -> Tools -> About
  3333. //-----------------------------------------------------------------------------
  3334. void ImGui::ShowAboutWindow(bool* p_open)
  3335. {
  3336. if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
  3337. {
  3338. ImGui::End();
  3339. return;
  3340. }
  3341. ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
  3342. ImGui::Separator();
  3343. ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
  3344. ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
  3345. static bool show_config_info = false;
  3346. ImGui::Checkbox("Config/Build Information", &show_config_info);
  3347. if (show_config_info)
  3348. {
  3349. ImGuiIO& io = ImGui::GetIO();
  3350. ImGuiStyle& style = ImGui::GetStyle();
  3351. bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
  3352. ImVec2 child_size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18);
  3353. ImGui::BeginChildFrame(ImGui::GetID("cfg_infos"), child_size, ImGuiWindowFlags_NoMove);
  3354. if (copy_to_clipboard)
  3355. {
  3356. ImGui::LogToClipboard();
  3357. ImGui::LogText("```\n"); // Back quotes will make text appears without formatting when pasting on GitHub
  3358. }
  3359. ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
  3360. ImGui::Separator();
  3361. ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert));
  3362. ImGui::Text("define: __cplusplus=%d", (int)__cplusplus);
  3363. #ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
  3364. ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
  3365. #endif
  3366. #ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
  3367. ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
  3368. #endif
  3369. #ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
  3370. ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS");
  3371. #endif
  3372. #ifdef IMGUI_DISABLE_WIN32_FUNCTIONS
  3373. ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS");
  3374. #endif
  3375. #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
  3376. ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS");
  3377. #endif
  3378. #ifdef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
  3379. ImGui::Text("define: IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS");
  3380. #endif
  3381. #ifdef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
  3382. ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS");
  3383. #endif
  3384. #ifdef IMGUI_DISABLE_FILE_FUNCTIONS
  3385. ImGui::Text("define: IMGUI_DISABLE_FILE_FUNCTIONS");
  3386. #endif
  3387. #ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS
  3388. ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS");
  3389. #endif
  3390. #ifdef IMGUI_USE_BGRA_PACKED_COLOR
  3391. ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR");
  3392. #endif
  3393. #ifdef _WIN32
  3394. ImGui::Text("define: _WIN32");
  3395. #endif
  3396. #ifdef _WIN64
  3397. ImGui::Text("define: _WIN64");
  3398. #endif
  3399. #ifdef __linux__
  3400. ImGui::Text("define: __linux__");
  3401. #endif
  3402. #ifdef __APPLE__
  3403. ImGui::Text("define: __APPLE__");
  3404. #endif
  3405. #ifdef _MSC_VER
  3406. ImGui::Text("define: _MSC_VER=%d", _MSC_VER);
  3407. #endif
  3408. #ifdef __MINGW32__
  3409. ImGui::Text("define: __MINGW32__");
  3410. #endif
  3411. #ifdef __MINGW64__
  3412. ImGui::Text("define: __MINGW64__");
  3413. #endif
  3414. #ifdef __GNUC__
  3415. ImGui::Text("define: __GNUC__=%d", (int)__GNUC__);
  3416. #endif
  3417. #ifdef __clang_version__
  3418. ImGui::Text("define: __clang_version__=%s", __clang_version__);
  3419. #endif
  3420. #ifdef IMGUI_HAS_VIEWPORT
  3421. ImGui::Text("define: IMGUI_HAS_VIEWPORT");
  3422. #endif
  3423. #ifdef IMGUI_HAS_DOCK
  3424. ImGui::Text("define: IMGUI_HAS_DOCK");
  3425. #endif
  3426. ImGui::Separator();
  3427. ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
  3428. ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
  3429. ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
  3430. if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) ImGui::Text(" NavEnableKeyboard");
  3431. if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) ImGui::Text(" NavEnableGamepad");
  3432. if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) ImGui::Text(" NavEnableSetMousePos");
  3433. if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard) ImGui::Text(" NavNoCaptureKeyboard");
  3434. if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) ImGui::Text(" NoMouse");
  3435. if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) ImGui::Text(" NoMouseCursorChange");
  3436. if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) ImGui::Text(" DockingEnable");
  3437. if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) ImGui::Text(" ViewportsEnable");
  3438. if (io.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports) ImGui::Text(" DpiEnableScaleViewports");
  3439. if (io.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ImGui::Text(" DpiEnableScaleFonts");
  3440. if (io.MouseDrawCursor) ImGui::Text("io.MouseDrawCursor");
  3441. if (io.ConfigViewportsNoAutoMerge) ImGui::Text("io.ConfigViewportsNoAutoMerge");
  3442. if (io.ConfigViewportsNoTaskBarIcon) ImGui::Text("io.ConfigViewportsNoTaskBarIcon");
  3443. if (io.ConfigViewportsNoDecoration) ImGui::Text("io.ConfigViewportsNoDecoration");
  3444. if (io.ConfigViewportsNoDefaultParent) ImGui::Text("io.ConfigViewportsNoDefaultParent");
  3445. if (io.ConfigDockingNoSplit) ImGui::Text("io.ConfigDockingNoSplit");
  3446. if (io.ConfigDockingWithShift) ImGui::Text("io.ConfigDockingWithShift");
  3447. if (io.ConfigDockingAlwaysTabBar) ImGui::Text("io.ConfigDockingAlwaysTabBar");
  3448. if (io.ConfigDockingTransparentPayload) ImGui::Text("io.ConfigDockingTransparentPayload");
  3449. if (io.ConfigMacOSXBehaviors) ImGui::Text("io.ConfigMacOSXBehaviors");
  3450. if (io.ConfigInputTextCursorBlink) ImGui::Text("io.ConfigInputTextCursorBlink");
  3451. if (io.ConfigWindowsResizeFromEdges) ImGui::Text("io.ConfigWindowsResizeFromEdges");
  3452. if (io.ConfigWindowsMoveFromTitleBarOnly) ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
  3453. if (io.ConfigMemoryCompactTimer >= 0.0f) ImGui::Text("io.ConfigMemoryCompactTimer = %.1f", io.ConfigMemoryCompactTimer);
  3454. ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags);
  3455. if (io.BackendFlags & ImGuiBackendFlags_HasGamepad) ImGui::Text(" HasGamepad");
  3456. if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) ImGui::Text(" HasMouseCursors");
  3457. if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos) ImGui::Text(" HasSetMousePos");
  3458. if (io.BackendFlags & ImGuiBackendFlags_PlatformHasViewports) ImGui::Text(" PlatformHasViewports");
  3459. if (io.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport)ImGui::Text(" HasMouseHoveredViewport");
  3460. if (io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) ImGui::Text(" RendererHasVtxOffset");
  3461. if (io.BackendFlags & ImGuiBackendFlags_RendererHasViewports) ImGui::Text(" RendererHasViewports");
  3462. ImGui::Separator();
  3463. ImGui::Text("io.Fonts: %d fonts, Flags: 0x%08X, TexSize: %d,%d", io.Fonts->Fonts.Size, io.Fonts->Flags, io.Fonts->TexWidth, io.Fonts->TexHeight);
  3464. ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y);
  3465. ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
  3466. ImGui::Separator();
  3467. ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y);
  3468. ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize);
  3469. ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y);
  3470. ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding);
  3471. ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize);
  3472. ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y);
  3473. ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y);
  3474. if (copy_to_clipboard)
  3475. {
  3476. ImGui::LogText("\n```\n");
  3477. ImGui::LogFinish();
  3478. }
  3479. ImGui::EndChildFrame();
  3480. }
  3481. ImGui::End();
  3482. }
  3483. //-----------------------------------------------------------------------------
  3484. // [SECTION] Style Editor / ShowStyleEditor()
  3485. //-----------------------------------------------------------------------------
  3486. // - ShowStyleSelector()
  3487. // - ShowFontSelector()
  3488. // - ShowStyleEditor()
  3489. //-----------------------------------------------------------------------------
  3490. // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
  3491. // Here we use the simplified Combo() api that packs items into a single literal string.
  3492. // Useful for quick combo boxes where the choices are known locally.
  3493. bool ImGui::ShowStyleSelector(const char* label)
  3494. {
  3495. static int style_idx = -1;
  3496. if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
  3497. {
  3498. switch (style_idx)
  3499. {
  3500. case 0: ImGui::StyleColorsClassic(); break;
  3501. case 1: ImGui::StyleColorsDark(); break;
  3502. case 2: ImGui::StyleColorsLight(); break;
  3503. }
  3504. return true;
  3505. }
  3506. return false;
  3507. }
  3508. // Demo helper function to select among loaded fonts.
  3509. // Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
  3510. void ImGui::ShowFontSelector(const char* label)
  3511. {
  3512. ImGuiIO& io = ImGui::GetIO();
  3513. ImFont* font_current = ImGui::GetFont();
  3514. if (ImGui::BeginCombo(label, font_current->GetDebugName()))
  3515. {
  3516. for (int n = 0; n < io.Fonts->Fonts.Size; n++)
  3517. {
  3518. ImFont* font = io.Fonts->Fonts[n];
  3519. ImGui::PushID((void*)font);
  3520. if (ImGui::Selectable(font->GetDebugName(), font == font_current))
  3521. io.FontDefault = font;
  3522. ImGui::PopID();
  3523. }
  3524. ImGui::EndCombo();
  3525. }
  3526. ImGui::SameLine();
  3527. HelpMarker(
  3528. "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
  3529. "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
  3530. "- Read FAQ and docs/FONTS.md for more details.\n"
  3531. "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
  3532. }
  3533. // [Internal] Display details for a single font, called by ShowStyleEditor().
  3534. static void NodeFont(ImFont* font)
  3535. {
  3536. ImGuiIO& io = ImGui::GetIO();
  3537. ImGuiStyle& style = ImGui::GetStyle();
  3538. bool font_details_opened = ImGui::TreeNode(font, "Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)",
  3539. font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);
  3540. ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { io.FontDefault = font; }
  3541. if (!font_details_opened)
  3542. return;
  3543. ImGui::PushFont(font);
  3544. ImGui::Text("The quick brown fox jumps over the lazy dog");
  3545. ImGui::PopFont();
  3546. ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font
  3547. ImGui::SameLine(); HelpMarker(
  3548. "Note than the default embedded font is NOT meant to be scaled.\n\n"
  3549. "Font are currently rendered into bitmaps at a given size at the time of building the atlas. "
  3550. "You may oversample them to get some flexibility with scaling. "
  3551. "You can also render at multiple sizes and select which one to use at runtime.\n\n"
  3552. "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
  3553. ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
  3554. ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar);
  3555. ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar, font->EllipsisChar);
  3556. const int surface_sqrt = (int)sqrtf((float)font->MetricsTotalSurface);
  3557. ImGui::Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);
  3558. for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
  3559. if (font->ConfigData)
  3560. if (const ImFontConfig* cfg = &font->ConfigData[config_i])
  3561. ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
  3562. config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);
  3563. if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
  3564. {
  3565. // Display all glyphs of the fonts in separate pages of 256 characters
  3566. const ImU32 glyph_col = ImGui::GetColorU32(ImGuiCol_Text);
  3567. for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
  3568. {
  3569. // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k)
  3570. // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT
  3571. // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here)
  3572. if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))
  3573. {
  3574. base += 4096 - 256;
  3575. continue;
  3576. }
  3577. int count = 0;
  3578. for (unsigned int n = 0; n < 256; n++)
  3579. if (font->FindGlyphNoFallback((ImWchar)(base + n)))
  3580. count++;
  3581. if (count <= 0)
  3582. continue;
  3583. if (!ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))
  3584. continue;
  3585. float cell_size = font->FontSize * 1;
  3586. float cell_spacing = style.ItemSpacing.y;
  3587. ImVec2 base_pos = ImGui::GetCursorScreenPos();
  3588. ImDrawList* draw_list = ImGui::GetWindowDrawList();
  3589. for (unsigned int n = 0; n < 256; n++)
  3590. {
  3591. // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions
  3592. // available here and thus cannot easily generate a zero-terminated UTF-8 encoded string.
  3593. ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
  3594. ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
  3595. const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
  3596. draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
  3597. if (glyph)
  3598. font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
  3599. if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
  3600. {
  3601. ImGui::BeginTooltip();
  3602. ImGui::Text("Codepoint: U+%04X", base + n);
  3603. ImGui::Separator();
  3604. ImGui::Text("Visible: %d", glyph->Visible);
  3605. ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
  3606. ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
  3607. ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
  3608. ImGui::EndTooltip();
  3609. }
  3610. }
  3611. ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
  3612. ImGui::TreePop();
  3613. }
  3614. ImGui::TreePop();
  3615. }
  3616. ImGui::TreePop();
  3617. }
  3618. void ImGui::ShowStyleEditor(ImGuiStyle* ref)
  3619. {
  3620. // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to
  3621. // (without a reference style pointer, we will use one compared locally as a reference)
  3622. ImGuiStyle& style = ImGui::GetStyle();
  3623. static ImGuiStyle ref_saved_style;
  3624. // Default to using internal storage as reference
  3625. static bool init = true;
  3626. if (init && ref == NULL)
  3627. ref_saved_style = style;
  3628. init = false;
  3629. if (ref == NULL)
  3630. ref = &ref_saved_style;
  3631. ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
  3632. if (ImGui::ShowStyleSelector("Colors##Selector"))
  3633. ref_saved_style = style;
  3634. ImGui::ShowFontSelector("Fonts##Selector");
  3635. // Simplified Settings (expose floating-pointer border sizes as boolean representing 0.0f or 1.0f)
  3636. if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
  3637. style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
  3638. { bool border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &border)) { style.WindowBorderSize = border ? 1.0f : 0.0f; } }
  3639. ImGui::SameLine();
  3640. { bool border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &border)) { style.FrameBorderSize = border ? 1.0f : 0.0f; } }
  3641. ImGui::SameLine();
  3642. { bool border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &border)) { style.PopupBorderSize = border ? 1.0f : 0.0f; } }
  3643. // Save/Revert button
  3644. if (ImGui::Button("Save Ref"))
  3645. *ref = ref_saved_style = style;
  3646. ImGui::SameLine();
  3647. if (ImGui::Button("Revert Ref"))
  3648. style = *ref;
  3649. ImGui::SameLine();
  3650. HelpMarker(
  3651. "Save/Revert in local non-persistent storage. Default Colors definition are not affected. "
  3652. "Use \"Export\" below to save them somewhere.");
  3653. ImGui::Separator();
  3654. if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
  3655. {
  3656. if (ImGui::BeginTabItem("Sizes"))
  3657. {
  3658. ImGui::Text("Main");
  3659. ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
  3660. ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
  3661. ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
  3662. ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
  3663. ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
  3664. ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
  3665. ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
  3666. ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
  3667. ImGui::Text("Borders");
  3668. ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
  3669. ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
  3670. ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
  3671. ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
  3672. ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
  3673. ImGui::Text("Rounding");
  3674. ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f");
  3675. ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f");
  3676. ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
  3677. ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
  3678. ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
  3679. ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
  3680. ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
  3681. ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
  3682. ImGui::Text("Alignment");
  3683. ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
  3684. int window_menu_button_position = style.WindowMenuButtonPosition + 1;
  3685. if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
  3686. style.WindowMenuButtonPosition = window_menu_button_position - 1;
  3687. ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
  3688. ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
  3689. ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
  3690. ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f");
  3691. ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content.");
  3692. ImGui::Text("Safe Area Padding");
  3693. ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
  3694. ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
  3695. ImGui::EndTabItem();
  3696. }
  3697. if (ImGui::BeginTabItem("Colors"))
  3698. {
  3699. static int output_dest = 0;
  3700. static bool output_only_modified = true;
  3701. if (ImGui::Button("Export"))
  3702. {
  3703. if (output_dest == 0)
  3704. ImGui::LogToClipboard();
  3705. else
  3706. ImGui::LogToTTY();
  3707. ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
  3708. for (int i = 0; i < ImGuiCol_COUNT; i++)
  3709. {
  3710. const ImVec4& col = style.Colors[i];
  3711. const char* name = ImGui::GetStyleColorName(i);
  3712. if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
  3713. ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE,
  3714. name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
  3715. }
  3716. ImGui::LogFinish();
  3717. }
  3718. ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
  3719. ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
  3720. static ImGuiTextFilter filter;
  3721. filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
  3722. static ImGuiColorEditFlags alpha_flags = 0;
  3723. if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None)) { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine();
  3724. if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_AlphaPreview)) { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine();
  3725. if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine();
  3726. HelpMarker(
  3727. "In the color list:\n"
  3728. "Left-click on color square to open color picker,\n"
  3729. "Right-click to open edit options menu.");
  3730. ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
  3731. ImGui::PushItemWidth(-160);
  3732. for (int i = 0; i < ImGuiCol_COUNT; i++)
  3733. {
  3734. const char* name = ImGui::GetStyleColorName(i);
  3735. if (!filter.PassFilter(name))
  3736. continue;
  3737. ImGui::PushID(i);
  3738. ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
  3739. if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
  3740. {
  3741. // Tips: in a real user application, you may want to merge and use an icon font into the main font,
  3742. // so instead of "Save"/"Revert" you'd use icons!
  3743. // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
  3744. ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
  3745. ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
  3746. }
  3747. ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
  3748. ImGui::TextUnformatted(name);
  3749. ImGui::PopID();
  3750. }
  3751. ImGui::PopItemWidth();
  3752. ImGui::EndChild();
  3753. ImGui::EndTabItem();
  3754. }
  3755. if (ImGui::BeginTabItem("Fonts"))
  3756. {
  3757. ImGuiIO& io = ImGui::GetIO();
  3758. ImFontAtlas* atlas = io.Fonts;
  3759. HelpMarker("Read FAQ and docs/FONTS.md for details on font loading.");
  3760. ImGui::PushItemWidth(120);
  3761. for (int i = 0; i < atlas->Fonts.Size; i++)
  3762. {
  3763. ImFont* font = atlas->Fonts[i];
  3764. ImGui::PushID(font);
  3765. NodeFont(font);
  3766. ImGui::PopID();
  3767. }
  3768. if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
  3769. {
  3770. ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
  3771. ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
  3772. ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), tint_col, border_col);
  3773. ImGui::TreePop();
  3774. }
  3775. // Post-baking font scaling. Note that this is NOT the nice way of scaling fonts, read below.
  3776. // (we enforce hard clamping manually as by default DragFloat/SliderFloat allows CTRL+Click text to get out of bounds).
  3777. const float MIN_SCALE = 0.3f;
  3778. const float MAX_SCALE = 2.0f;
  3779. HelpMarker(
  3780. "Those are old settings provided for convenience.\n"
  3781. "However, the _correct_ way of scaling your UI is currently to reload your font at the designed size, "
  3782. "rebuild the font atlas, and call style.ScaleAllSizes() on a reference ImGuiStyle structure.\n"
  3783. "Using those settings here will give you poor quality results.");
  3784. static float window_scale = 1.0f;
  3785. if (ImGui::DragFloat("window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
  3786. ImGui::SetWindowFontScale(window_scale);
  3787. ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything
  3788. ImGui::PopItemWidth();
  3789. ImGui::EndTabItem();
  3790. }
  3791. if (ImGui::BeginTabItem("Rendering"))
  3792. {
  3793. ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
  3794. ImGui::SameLine();
  3795. HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
  3796. ImGui::Checkbox("Anti-aliased lines use texture", &style.AntiAliasedLinesUseTex);
  3797. ImGui::SameLine();
  3798. HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering).");
  3799. ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
  3800. ImGui::PushItemWidth(100);
  3801. ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
  3802. if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
  3803. // When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles.
  3804. ImGui::DragFloat("Circle Segment Max Error", &style.CircleSegmentMaxError, 0.01f, 0.10f, 10.0f, "%.2f");
  3805. if (ImGui::IsItemActive())
  3806. {
  3807. ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
  3808. ImGui::BeginTooltip();
  3809. ImVec2 p = ImGui::GetCursorScreenPos();
  3810. ImDrawList* draw_list = ImGui::GetWindowDrawList();
  3811. float RAD_MIN = 10.0f, RAD_MAX = 80.0f;
  3812. float off_x = 10.0f;
  3813. for (int n = 0; n < 7; n++)
  3814. {
  3815. const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (7.0f - 1.0f);
  3816. draw_list->AddCircle(ImVec2(p.x + off_x + rad, p.y + RAD_MAX), rad, ImGui::GetColorU32(ImGuiCol_Text), 0);
  3817. off_x += 10.0f + rad * 2.0f;
  3818. }
  3819. ImGui::Dummy(ImVec2(off_x, RAD_MAX * 2.0f));
  3820. ImGui::EndTooltip();
  3821. }
  3822. ImGui::SameLine();
  3823. HelpMarker("When drawing circle primitives with \"num_segments == 0\" tesselation will be calculated automatically.");
  3824. ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.
  3825. ImGui::PopItemWidth();
  3826. ImGui::EndTabItem();
  3827. }
  3828. ImGui::EndTabBar();
  3829. }
  3830. ImGui::PopItemWidth();
  3831. }
  3832. //-----------------------------------------------------------------------------
  3833. // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
  3834. //-----------------------------------------------------------------------------
  3835. // - ShowExampleAppMainMenuBar()
  3836. // - ShowExampleMenuFile()
  3837. //-----------------------------------------------------------------------------
  3838. // Demonstrate creating a "main" fullscreen menu bar and populating it.
  3839. // Note the difference between BeginMainMenuBar() and BeginMenuBar():
  3840. // - BeginMenuBar() = menu-bar inside current window (which needs the ImGuiWindowFlags_MenuBar flag!)
  3841. // - BeginMainMenuBar() = helper to create menu-bar-sized window at the top of the main viewport + call BeginMenuBar() into it.
  3842. static void ShowExampleAppMainMenuBar()
  3843. {
  3844. if (ImGui::BeginMainMenuBar())
  3845. {
  3846. if (ImGui::BeginMenu("File"))
  3847. {
  3848. ShowExampleMenuFile();
  3849. ImGui::EndMenu();
  3850. }
  3851. if (ImGui::BeginMenu("Edit"))
  3852. {
  3853. if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
  3854. if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item
  3855. ImGui::Separator();
  3856. if (ImGui::MenuItem("Cut", "CTRL+X")) {}
  3857. if (ImGui::MenuItem("Copy", "CTRL+C")) {}
  3858. if (ImGui::MenuItem("Paste", "CTRL+V")) {}
  3859. ImGui::EndMenu();
  3860. }
  3861. ImGui::EndMainMenuBar();
  3862. }
  3863. }
  3864. // Note that shortcuts are currently provided for display only
  3865. // (future version will add explicit flags to BeginMenu() to request processing shortcuts)
  3866. static void ShowExampleMenuFile()
  3867. {
  3868. ImGui::MenuItem("(demo menu)", NULL, false, false);
  3869. if (ImGui::MenuItem("New")) {}
  3870. if (ImGui::MenuItem("Open", "Ctrl+O")) {}
  3871. if (ImGui::BeginMenu("Open Recent"))
  3872. {
  3873. ImGui::MenuItem("fish_hat.c");
  3874. ImGui::MenuItem("fish_hat.inl");
  3875. ImGui::MenuItem("fish_hat.h");
  3876. if (ImGui::BeginMenu("More.."))
  3877. {
  3878. ImGui::MenuItem("Hello");
  3879. ImGui::MenuItem("Sailor");
  3880. if (ImGui::BeginMenu("Recurse.."))
  3881. {
  3882. ShowExampleMenuFile();
  3883. ImGui::EndMenu();
  3884. }
  3885. ImGui::EndMenu();
  3886. }
  3887. ImGui::EndMenu();
  3888. }
  3889. if (ImGui::MenuItem("Save", "Ctrl+S")) {}
  3890. if (ImGui::MenuItem("Save As..")) {}
  3891. ImGui::Separator();
  3892. if (ImGui::BeginMenu("Options"))
  3893. {
  3894. static bool enabled = true;
  3895. ImGui::MenuItem("Enabled", "", &enabled);
  3896. ImGui::BeginChild("child", ImVec2(0, 60), true);
  3897. for (int i = 0; i < 10; i++)
  3898. ImGui::Text("Scrolling Text %d", i);
  3899. ImGui::EndChild();
  3900. static float f = 0.5f;
  3901. static int n = 0;
  3902. ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
  3903. ImGui::InputFloat("Input", &f, 0.1f);
  3904. ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
  3905. ImGui::EndMenu();
  3906. }
  3907. if (ImGui::BeginMenu("Colors"))
  3908. {
  3909. float sz = ImGui::GetTextLineHeight();
  3910. for (int i = 0; i < ImGuiCol_COUNT; i++)
  3911. {
  3912. const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
  3913. ImVec2 p = ImGui::GetCursorScreenPos();
  3914. ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i));
  3915. ImGui::Dummy(ImVec2(sz, sz));
  3916. ImGui::SameLine();
  3917. ImGui::MenuItem(name);
  3918. }
  3919. ImGui::EndMenu();
  3920. }
  3921. // Here we demonstrate appending again to the "Options" menu (which we already created above)
  3922. // Of course in this demo it is a little bit silly that this function calls BeginMenu("Options") twice.
  3923. // In a real code-base using it would make senses to use this feature from very different code locations.
  3924. if (ImGui::BeginMenu("Options")) // <-- Append!
  3925. {
  3926. static bool b = true;
  3927. ImGui::Checkbox("SomeOption", &b);
  3928. ImGui::EndMenu();
  3929. }
  3930. if (ImGui::BeginMenu("Disabled", false)) // Disabled
  3931. {
  3932. IM_ASSERT(0);
  3933. }
  3934. if (ImGui::MenuItem("Checked", NULL, true)) {}
  3935. if (ImGui::MenuItem("Quit", "Alt+F4")) {}
  3936. }
  3937. //-----------------------------------------------------------------------------
  3938. // [SECTION] Example App: Debug Console / ShowExampleAppConsole()
  3939. //-----------------------------------------------------------------------------
  3940. // Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
  3941. // For the console example, we are using a more C++ like approach of declaring a class to hold both data and functions.
  3942. struct ExampleAppConsole
  3943. {
  3944. char InputBuf[256];
  3945. ImVector<char*> Items;
  3946. ImVector<const char*> Commands;
  3947. ImVector<char*> History;
  3948. int HistoryPos; // -1: new line, 0..History.Size-1 browsing history.
  3949. ImGuiTextFilter Filter;
  3950. bool AutoScroll;
  3951. bool ScrollToBottom;
  3952. ExampleAppConsole()
  3953. {
  3954. ClearLog();
  3955. memset(InputBuf, 0, sizeof(InputBuf));
  3956. HistoryPos = -1;
  3957. // "CLASSIFY" is here to provide the test case where "C"+[tab] completes to "CL" and display multiple matches.
  3958. Commands.push_back("HELP");
  3959. Commands.push_back("HISTORY");
  3960. Commands.push_back("CLEAR");
  3961. Commands.push_back("CLASSIFY");
  3962. AutoScroll = true;
  3963. ScrollToBottom = false;
  3964. AddLog("Welcome to Dear ImGui!");
  3965. }
  3966. ~ExampleAppConsole()
  3967. {
  3968. ClearLog();
  3969. for (int i = 0; i < History.Size; i++)
  3970. free(History[i]);
  3971. }
  3972. // Portable helpers
  3973. static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
  3974. static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; }
  3975. static char* Strdup(const char* s) { size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
  3976. static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
  3977. void ClearLog()
  3978. {
  3979. for (int i = 0; i < Items.Size; i++)
  3980. free(Items[i]);
  3981. Items.clear();
  3982. }
  3983. void AddLog(const char* fmt, ...) IM_FMTARGS(2)
  3984. {
  3985. // FIXME-OPT
  3986. char buf[1024];
  3987. va_list args;
  3988. va_start(args, fmt);
  3989. vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
  3990. buf[IM_ARRAYSIZE(buf)-1] = 0;
  3991. va_end(args);
  3992. Items.push_back(Strdup(buf));
  3993. }
  3994. void Draw(const char* title, bool* p_open)
  3995. {
  3996. ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
  3997. if (!ImGui::Begin(title, p_open))
  3998. {
  3999. ImGui::End();
  4000. return;
  4001. }
  4002. // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar.
  4003. // So e.g. IsItemHovered() will return true when hovering the title bar.
  4004. // Here we create a context menu only available from the title bar.
  4005. if (ImGui::BeginPopupContextItem())
  4006. {
  4007. if (ImGui::MenuItem("Close Console"))
  4008. *p_open = false;
  4009. ImGui::EndPopup();
  4010. }
  4011. ImGui::TextWrapped(
  4012. "This example implements a console with basic coloring, completion (TAB key) and history (Up/Down keys). A more elaborate "
  4013. "implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
  4014. ImGui::TextWrapped("Enter 'HELP' for help.");
  4015. // TODO: display items starting from the bottom
  4016. if (ImGui::SmallButton("Add Debug Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); }
  4017. ImGui::SameLine();
  4018. if (ImGui::SmallButton("Add Debug Error")) { AddLog("[error] something went wrong"); }
  4019. ImGui::SameLine();
  4020. if (ImGui::SmallButton("Clear")) { ClearLog(); }
  4021. ImGui::SameLine();
  4022. bool copy_to_clipboard = ImGui::SmallButton("Copy");
  4023. //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
  4024. ImGui::Separator();
  4025. // Options menu
  4026. if (ImGui::BeginPopup("Options"))
  4027. {
  4028. ImGui::Checkbox("Auto-scroll", &AutoScroll);
  4029. ImGui::EndPopup();
  4030. }
  4031. // Options, Filter
  4032. if (ImGui::Button("Options"))
  4033. ImGui::OpenPopup("Options");
  4034. ImGui::SameLine();
  4035. Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
  4036. ImGui::Separator();
  4037. // Reserve enough left-over height for 1 separator + 1 input text
  4038. const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
  4039. ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar);
  4040. if (ImGui::BeginPopupContextWindow())
  4041. {
  4042. if (ImGui::Selectable("Clear")) ClearLog();
  4043. ImGui::EndPopup();
  4044. }
  4045. // Display every line as a separate entry so we can change their color or add custom widgets.
  4046. // If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
  4047. // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping
  4048. // to only process visible items. The clipper will automatically measure the height of your first item and then
  4049. // "seek" to display only items in the visible area.
  4050. // To use the clipper we can replace your standard loop:
  4051. // for (int i = 0; i < Items.Size; i++)
  4052. // With:
  4053. // ImGuiListClipper clipper;
  4054. // clipper.Begin(Items.Size);
  4055. // while (clipper.Step())
  4056. // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
  4057. // - That your items are evenly spaced (same height)
  4058. // - That you have cheap random access to your elements (you can access them given their index,
  4059. // without processing all the ones before)
  4060. // You cannot this code as-is if a filter is active because it breaks the 'cheap random-access' property.
  4061. // We would need random-access on the post-filtered list.
  4062. // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices
  4063. // or offsets of items that passed the filtering test, recomputing this array when user changes the filter,
  4064. // and appending newly elements as they are inserted. This is left as a task to the user until we can manage
  4065. // to improve this example code!
  4066. // If your items are of variable height:
  4067. // - Split them into same height items would be simpler and facilitate random-seeking into your list.
  4068. // - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items.
  4069. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
  4070. if (copy_to_clipboard)
  4071. ImGui::LogToClipboard();
  4072. for (int i = 0; i < Items.Size; i++)
  4073. {
  4074. const char* item = Items[i];
  4075. if (!Filter.PassFilter(item))
  4076. continue;
  4077. // Normally you would store more information in your item than just a string.
  4078. // (e.g. make Items[] an array of structure, store color/type etc.)
  4079. ImVec4 color;
  4080. bool has_color = false;
  4081. if (strstr(item, "[error]")) { color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); has_color = true; }
  4082. else if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.0f, 0.8f, 0.6f, 1.0f); has_color = true; }
  4083. if (has_color)
  4084. ImGui::PushStyleColor(ImGuiCol_Text, color);
  4085. ImGui::TextUnformatted(item);
  4086. if (has_color)
  4087. ImGui::PopStyleColor();
  4088. }
  4089. if (copy_to_clipboard)
  4090. ImGui::LogFinish();
  4091. if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
  4092. ImGui::SetScrollHereY(1.0f);
  4093. ScrollToBottom = false;
  4094. ImGui::PopStyleVar();
  4095. ImGui::EndChild();
  4096. ImGui::Separator();
  4097. // Command-line
  4098. bool reclaim_focus = false;
  4099. ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
  4100. if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
  4101. {
  4102. char* s = InputBuf;
  4103. Strtrim(s);
  4104. if (s[0])
  4105. ExecCommand(s);
  4106. strcpy(s, "");
  4107. reclaim_focus = true;
  4108. }
  4109. // Auto-focus on window apparition
  4110. ImGui::SetItemDefaultFocus();
  4111. if (reclaim_focus)
  4112. ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
  4113. ImGui::End();
  4114. }
  4115. void ExecCommand(const char* command_line)
  4116. {
  4117. AddLog("# %s\n", command_line);
  4118. // Insert into history. First find match and delete it so it can be pushed to the back.
  4119. // This isn't trying to be smart or optimal.
  4120. HistoryPos = -1;
  4121. for (int i = History.Size - 1; i >= 0; i--)
  4122. if (Stricmp(History[i], command_line) == 0)
  4123. {
  4124. free(History[i]);
  4125. History.erase(History.begin() + i);
  4126. break;
  4127. }
  4128. History.push_back(Strdup(command_line));
  4129. // Process command
  4130. if (Stricmp(command_line, "CLEAR") == 0)
  4131. {
  4132. ClearLog();
  4133. }
  4134. else if (Stricmp(command_line, "HELP") == 0)
  4135. {
  4136. AddLog("Commands:");
  4137. for (int i = 0; i < Commands.Size; i++)
  4138. AddLog("- %s", Commands[i]);
  4139. }
  4140. else if (Stricmp(command_line, "HISTORY") == 0)
  4141. {
  4142. int first = History.Size - 10;
  4143. for (int i = first > 0 ? first : 0; i < History.Size; i++)
  4144. AddLog("%3d: %s\n", i, History[i]);
  4145. }
  4146. else
  4147. {
  4148. AddLog("Unknown command: '%s'\n", command_line);
  4149. }
  4150. // On command input, we scroll to bottom even if AutoScroll==false
  4151. ScrollToBottom = true;
  4152. }
  4153. // In C++11 you'd be better off using lambdas for this sort of forwarding callbacks
  4154. static int TextEditCallbackStub(ImGuiInputTextCallbackData* data)
  4155. {
  4156. ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
  4157. return console->TextEditCallback(data);
  4158. }
  4159. int TextEditCallback(ImGuiInputTextCallbackData* data)
  4160. {
  4161. //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
  4162. switch (data->EventFlag)
  4163. {
  4164. case ImGuiInputTextFlags_CallbackCompletion:
  4165. {
  4166. // Example of TEXT COMPLETION
  4167. // Locate beginning of current word
  4168. const char* word_end = data->Buf + data->CursorPos;
  4169. const char* word_start = word_end;
  4170. while (word_start > data->Buf)
  4171. {
  4172. const char c = word_start[-1];
  4173. if (c == ' ' || c == '\t' || c == ',' || c == ';')
  4174. break;
  4175. word_start--;
  4176. }
  4177. // Build a list of candidates
  4178. ImVector<const char*> candidates;
  4179. for (int i = 0; i < Commands.Size; i++)
  4180. if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0)
  4181. candidates.push_back(Commands[i]);
  4182. if (candidates.Size == 0)
  4183. {
  4184. // No match
  4185. AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start);
  4186. }
  4187. else if (candidates.Size == 1)
  4188. {
  4189. // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing.
  4190. data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
  4191. data->InsertChars(data->CursorPos, candidates[0]);
  4192. data->InsertChars(data->CursorPos, " ");
  4193. }
  4194. else
  4195. {
  4196. // Multiple matches. Complete as much as we can..
  4197. // So inputing "C"+Tab will complete to "CL" then display "CLEAR" and "CLASSIFY" as matches.
  4198. int match_len = (int)(word_end - word_start);
  4199. for (;;)
  4200. {
  4201. int c = 0;
  4202. bool all_candidates_matches = true;
  4203. for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
  4204. if (i == 0)
  4205. c = toupper(candidates[i][match_len]);
  4206. else if (c == 0 || c != toupper(candidates[i][match_len]))
  4207. all_candidates_matches = false;
  4208. if (!all_candidates_matches)
  4209. break;
  4210. match_len++;
  4211. }
  4212. if (match_len > 0)
  4213. {
  4214. data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
  4215. data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
  4216. }
  4217. // List matches
  4218. AddLog("Possible matches:\n");
  4219. for (int i = 0; i < candidates.Size; i++)
  4220. AddLog("- %s\n", candidates[i]);
  4221. }
  4222. break;
  4223. }
  4224. case ImGuiInputTextFlags_CallbackHistory:
  4225. {
  4226. // Example of HISTORY
  4227. const int prev_history_pos = HistoryPos;
  4228. if (data->EventKey == ImGuiKey_UpArrow)
  4229. {
  4230. if (HistoryPos == -1)
  4231. HistoryPos = History.Size - 1;
  4232. else if (HistoryPos > 0)
  4233. HistoryPos--;
  4234. }
  4235. else if (data->EventKey == ImGuiKey_DownArrow)
  4236. {
  4237. if (HistoryPos != -1)
  4238. if (++HistoryPos >= History.Size)
  4239. HistoryPos = -1;
  4240. }
  4241. // A better implementation would preserve the data on the current input line along with cursor position.
  4242. if (prev_history_pos != HistoryPos)
  4243. {
  4244. const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
  4245. data->DeleteChars(0, data->BufTextLen);
  4246. data->InsertChars(0, history_str);
  4247. }
  4248. }
  4249. }
  4250. return 0;
  4251. }
  4252. };
  4253. static void ShowExampleAppConsole(bool* p_open)
  4254. {
  4255. static ExampleAppConsole console;
  4256. console.Draw("Example: Console", p_open);
  4257. }
  4258. //-----------------------------------------------------------------------------
  4259. // [SECTION] Example App: Debug Log / ShowExampleAppLog()
  4260. //-----------------------------------------------------------------------------
  4261. // Usage:
  4262. // static ExampleAppLog my_log;
  4263. // my_log.AddLog("Hello %d world\n", 123);
  4264. // my_log.Draw("title");
  4265. struct ExampleAppLog
  4266. {
  4267. ImGuiTextBuffer Buf;
  4268. ImGuiTextFilter Filter;
  4269. ImVector<int> LineOffsets; // Index to lines offset. We maintain this with AddLog() calls.
  4270. bool AutoScroll; // Keep scrolling if already at the bottom.
  4271. ExampleAppLog()
  4272. {
  4273. AutoScroll = true;
  4274. Clear();
  4275. }
  4276. void Clear()
  4277. {
  4278. Buf.clear();
  4279. LineOffsets.clear();
  4280. LineOffsets.push_back(0);
  4281. }
  4282. void AddLog(const char* fmt, ...) IM_FMTARGS(2)
  4283. {
  4284. int old_size = Buf.size();
  4285. va_list args;
  4286. va_start(args, fmt);
  4287. Buf.appendfv(fmt, args);
  4288. va_end(args);
  4289. for (int new_size = Buf.size(); old_size < new_size; old_size++)
  4290. if (Buf[old_size] == '\n')
  4291. LineOffsets.push_back(old_size + 1);
  4292. }
  4293. void Draw(const char* title, bool* p_open = NULL)
  4294. {
  4295. if (!ImGui::Begin(title, p_open))
  4296. {
  4297. ImGui::End();
  4298. return;
  4299. }
  4300. // Options menu
  4301. if (ImGui::BeginPopup("Options"))
  4302. {
  4303. ImGui::Checkbox("Auto-scroll", &AutoScroll);
  4304. ImGui::EndPopup();
  4305. }
  4306. // Main window
  4307. if (ImGui::Button("Options"))
  4308. ImGui::OpenPopup("Options");
  4309. ImGui::SameLine();
  4310. bool clear = ImGui::Button("Clear");
  4311. ImGui::SameLine();
  4312. bool copy = ImGui::Button("Copy");
  4313. ImGui::SameLine();
  4314. Filter.Draw("Filter", -100.0f);
  4315. ImGui::Separator();
  4316. ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
  4317. if (clear)
  4318. Clear();
  4319. if (copy)
  4320. ImGui::LogToClipboard();
  4321. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
  4322. const char* buf = Buf.begin();
  4323. const char* buf_end = Buf.end();
  4324. if (Filter.IsActive())
  4325. {
  4326. // In this example we don't use the clipper when Filter is enabled.
  4327. // This is because we don't have a random access on the result on our filter.
  4328. // A real application processing logs with ten of thousands of entries may want to store the result of
  4329. // search/filter.. especially if the filtering function is not trivial (e.g. reg-exp).
  4330. for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
  4331. {
  4332. const char* line_start = buf + LineOffsets[line_no];
  4333. const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
  4334. if (Filter.PassFilter(line_start, line_end))
  4335. ImGui::TextUnformatted(line_start, line_end);
  4336. }
  4337. }
  4338. else
  4339. {
  4340. // The simplest and easy way to display the entire buffer:
  4341. // ImGui::TextUnformatted(buf_begin, buf_end);
  4342. // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward
  4343. // to skip non-visible lines. Here we instead demonstrate using the clipper to only process lines that are
  4344. // within the visible area.
  4345. // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them
  4346. // on your side is recommended. Using ImGuiListClipper requires
  4347. // - A) random access into your data
  4348. // - B) items all being the same height,
  4349. // both of which we can handle since we an array pointing to the beginning of each line of text.
  4350. // When using the filter (in the block of code above) we don't have random access into the data to display
  4351. // anymore, which is why we don't use the clipper. Storing or skimming through the search result would make
  4352. // it possible (and would be recommended if you want to search through tens of thousands of entries).
  4353. ImGuiListClipper clipper;
  4354. clipper.Begin(LineOffsets.Size);
  4355. while (clipper.Step())
  4356. {
  4357. for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
  4358. {
  4359. const char* line_start = buf + LineOffsets[line_no];
  4360. const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
  4361. ImGui::TextUnformatted(line_start, line_end);
  4362. }
  4363. }
  4364. clipper.End();
  4365. }
  4366. ImGui::PopStyleVar();
  4367. if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
  4368. ImGui::SetScrollHereY(1.0f);
  4369. ImGui::EndChild();
  4370. ImGui::End();
  4371. }
  4372. };
  4373. // Demonstrate creating a simple log window with basic filtering.
  4374. static void ShowExampleAppLog(bool* p_open)
  4375. {
  4376. static ExampleAppLog log;
  4377. // For the demo: add a debug button _BEFORE_ the normal log window contents
  4378. // We take advantage of a rarely used feature: multiple calls to Begin()/End() are appending to the _same_ window.
  4379. // Most of the contents of the window will be added by the log.Draw() call.
  4380. ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
  4381. ImGui::Begin("Example: Log", p_open);
  4382. if (ImGui::SmallButton("[Debug] Add 5 entries"))
  4383. {
  4384. static int counter = 0;
  4385. const char* categories[3] = { "info", "warn", "error" };
  4386. const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
  4387. for (int n = 0; n < 5; n++)
  4388. {
  4389. const char* category = categories[counter % IM_ARRAYSIZE(categories)];
  4390. const char* word = words[counter % IM_ARRAYSIZE(words)];
  4391. log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
  4392. ImGui::GetFrameCount(), category, ImGui::GetTime(), word);
  4393. counter++;
  4394. }
  4395. }
  4396. ImGui::End();
  4397. // Actually call in the regular Log helper (which will Begin() into the same window as we just did)
  4398. log.Draw("Example: Log", p_open);
  4399. }
  4400. //-----------------------------------------------------------------------------
  4401. // [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
  4402. //-----------------------------------------------------------------------------
  4403. // Demonstrate create a window with multiple child windows.
  4404. static void ShowExampleAppLayout(bool* p_open)
  4405. {
  4406. ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
  4407. if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
  4408. {
  4409. if (ImGui::BeginMenuBar())
  4410. {
  4411. if (ImGui::BeginMenu("File"))
  4412. {
  4413. if (ImGui::MenuItem("Close")) *p_open = false;
  4414. ImGui::EndMenu();
  4415. }
  4416. ImGui::EndMenuBar();
  4417. }
  4418. // Left
  4419. static int selected = 0;
  4420. {
  4421. ImGui::BeginChild("left pane", ImVec2(150, 0), true);
  4422. for (int i = 0; i < 100; i++)
  4423. {
  4424. char label[128];
  4425. sprintf(label, "MyObject %d", i);
  4426. if (ImGui::Selectable(label, selected == i))
  4427. selected = i;
  4428. }
  4429. ImGui::EndChild();
  4430. }
  4431. ImGui::SameLine();
  4432. // Right
  4433. {
  4434. ImGui::BeginGroup();
  4435. ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
  4436. ImGui::Text("MyObject: %d", selected);
  4437. ImGui::Separator();
  4438. if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
  4439. {
  4440. if (ImGui::BeginTabItem("Description"))
  4441. {
  4442. ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
  4443. ImGui::EndTabItem();
  4444. }
  4445. if (ImGui::BeginTabItem("Details"))
  4446. {
  4447. ImGui::Text("ID: 0123456789");
  4448. ImGui::EndTabItem();
  4449. }
  4450. ImGui::EndTabBar();
  4451. }
  4452. ImGui::EndChild();
  4453. if (ImGui::Button("Revert")) {}
  4454. ImGui::SameLine();
  4455. if (ImGui::Button("Save")) {}
  4456. ImGui::EndGroup();
  4457. }
  4458. }
  4459. ImGui::End();
  4460. }
  4461. //-----------------------------------------------------------------------------
  4462. // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
  4463. //-----------------------------------------------------------------------------
  4464. static void ShowPlaceholderObject(const char* prefix, int uid)
  4465. {
  4466. // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
  4467. ImGui::PushID(uid);
  4468. // Text and Tree nodes are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the tree lines equal high.
  4469. ImGui::AlignTextToFramePadding();
  4470. bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
  4471. ImGui::NextColumn();
  4472. ImGui::AlignTextToFramePadding();
  4473. ImGui::Text("my sailor is rich");
  4474. ImGui::NextColumn();
  4475. if (node_open)
  4476. {
  4477. static float placeholder_members[8] = { 0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f };
  4478. for (int i = 0; i < 8; i++)
  4479. {
  4480. ImGui::PushID(i); // Use field index as identifier.
  4481. if (i < 2)
  4482. {
  4483. ShowPlaceholderObject("Child", 424242);
  4484. }
  4485. else
  4486. {
  4487. // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
  4488. ImGui::AlignTextToFramePadding();
  4489. ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet;
  4490. ImGui::TreeNodeEx("Field", flags, "Field_%d", i);
  4491. ImGui::NextColumn();
  4492. ImGui::SetNextItemWidth(-1);
  4493. if (i >= 5)
  4494. ImGui::InputFloat("##value", &placeholder_members[i], 1.0f);
  4495. else
  4496. ImGui::DragFloat("##value", &placeholder_members[i], 0.01f);
  4497. ImGui::NextColumn();
  4498. }
  4499. ImGui::PopID();
  4500. }
  4501. ImGui::TreePop();
  4502. }
  4503. ImGui::PopID();
  4504. }
  4505. // Demonstrate create a simple property editor.
  4506. static void ShowExampleAppPropertyEditor(bool* p_open)
  4507. {
  4508. ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
  4509. if (!ImGui::Begin("Example: Property editor", p_open))
  4510. {
  4511. ImGui::End();
  4512. return;
  4513. }
  4514. HelpMarker(
  4515. "This example shows how you may implement a property editor using two columns.\n"
  4516. "All objects/fields data are dummies here.\n"
  4517. "Remember that in many simple cases, you can use ImGui::SameLine(xxx) to position\n"
  4518. "your cursor horizontally instead of using the Columns() API.");
  4519. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
  4520. ImGui::Columns(2);
  4521. ImGui::Separator();
  4522. // Iterate placeholder objects (all the same data)
  4523. for (int obj_i = 0; obj_i < 3; obj_i++)
  4524. ShowPlaceholderObject("Object", obj_i);
  4525. ImGui::Columns(1);
  4526. ImGui::Separator();
  4527. ImGui::PopStyleVar();
  4528. ImGui::End();
  4529. }
  4530. //-----------------------------------------------------------------------------
  4531. // [SECTION] Example App: Long Text / ShowExampleAppLongText()
  4532. //-----------------------------------------------------------------------------
  4533. // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
  4534. static void ShowExampleAppLongText(bool* p_open)
  4535. {
  4536. ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
  4537. if (!ImGui::Begin("Example: Long text display", p_open))
  4538. {
  4539. ImGui::End();
  4540. return;
  4541. }
  4542. static int test_type = 0;
  4543. static ImGuiTextBuffer log;
  4544. static int lines = 0;
  4545. ImGui::Text("Printing unusually long amount of text.");
  4546. ImGui::Combo("Test type", &test_type,
  4547. "Single call to TextUnformatted()\0"
  4548. "Multiple calls to Text(), clipped\0"
  4549. "Multiple calls to Text(), not clipped (slow)\0");
  4550. ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
  4551. if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
  4552. ImGui::SameLine();
  4553. if (ImGui::Button("Add 1000 lines"))
  4554. {
  4555. for (int i = 0; i < 1000; i++)
  4556. log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
  4557. lines += 1000;
  4558. }
  4559. ImGui::BeginChild("Log");
  4560. switch (test_type)
  4561. {
  4562. case 0:
  4563. // Single call to TextUnformatted() with a big buffer
  4564. ImGui::TextUnformatted(log.begin(), log.end());
  4565. break;
  4566. case 1:
  4567. {
  4568. // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
  4569. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
  4570. ImGuiListClipper clipper;
  4571. clipper.Begin(lines);
  4572. while (clipper.Step())
  4573. for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
  4574. ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
  4575. ImGui::PopStyleVar();
  4576. break;
  4577. }
  4578. case 2:
  4579. // Multiple calls to Text(), not clipped (slow)
  4580. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
  4581. for (int i = 0; i < lines; i++)
  4582. ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
  4583. ImGui::PopStyleVar();
  4584. break;
  4585. }
  4586. ImGui::EndChild();
  4587. ImGui::End();
  4588. }
  4589. //-----------------------------------------------------------------------------
  4590. // [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
  4591. //-----------------------------------------------------------------------------
  4592. // Demonstrate creating a window which gets auto-resized according to its content.
  4593. static void ShowExampleAppAutoResize(bool* p_open)
  4594. {
  4595. if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
  4596. {
  4597. ImGui::End();
  4598. return;
  4599. }
  4600. static int lines = 10;
  4601. ImGui::TextUnformatted(
  4602. "Window will resize every-frame to the size of its content.\n"
  4603. "Note that you probably don't want to query the window size to\n"
  4604. "output your content because that would create a feedback loop.");
  4605. ImGui::SliderInt("Number of lines", &lines, 1, 20);
  4606. for (int i = 0; i < lines; i++)
  4607. ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
  4608. ImGui::End();
  4609. }
  4610. //-----------------------------------------------------------------------------
  4611. // [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
  4612. //-----------------------------------------------------------------------------
  4613. // Demonstrate creating a window with custom resize constraints.
  4614. static void ShowExampleAppConstrainedResize(bool* p_open)
  4615. {
  4616. struct CustomConstraints
  4617. {
  4618. // Helper functions to demonstrate programmatic constraints
  4619. static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize.x = data->DesiredSize.y = IM_MAX(data->DesiredSize.x, data->DesiredSize.y); }
  4620. static void Step(ImGuiSizeCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
  4621. };
  4622. const char* test_desc[] =
  4623. {
  4624. "Resize vertical only",
  4625. "Resize horizontal only",
  4626. "Width > 100, Height > 100",
  4627. "Width 400-500",
  4628. "Height 400-500",
  4629. "Custom: Always Square",
  4630. "Custom: Fixed Steps (100)",
  4631. };
  4632. static bool auto_resize = false;
  4633. static int type = 0;
  4634. static int display_lines = 10;
  4635. if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only
  4636. if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only
  4637. if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
  4638. if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500
  4639. if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500
  4640. if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square
  4641. if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step
  4642. ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
  4643. if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
  4644. {
  4645. if (ImGui::IsWindowDocked())
  4646. ImGui::Text("Warning: Sizing Constraints won't work if the window is docked!");
  4647. if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
  4648. if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
  4649. if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
  4650. ImGui::SetNextItemWidth(200);
  4651. ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
  4652. ImGui::SetNextItemWidth(200);
  4653. ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
  4654. ImGui::Checkbox("Auto-resize", &auto_resize);
  4655. for (int i = 0; i < display_lines; i++)
  4656. ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
  4657. }
  4658. ImGui::End();
  4659. }
  4660. //-----------------------------------------------------------------------------
  4661. // [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
  4662. //-----------------------------------------------------------------------------
  4663. // Demonstrate creating a simple static window with no decoration
  4664. // + a context-menu to choose which corner of the screen to use.
  4665. static void ShowExampleAppSimpleOverlay(bool* p_open)
  4666. {
  4667. // FIXME-VIEWPORT: Select a default viewport
  4668. const float DISTANCE = 10.0f;
  4669. static int corner = 0;
  4670. ImGuiIO& io = ImGui::GetIO();
  4671. ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
  4672. if (corner != -1)
  4673. {
  4674. window_flags |= ImGuiWindowFlags_NoMove;
  4675. ImGuiViewport* viewport = ImGui::GetMainViewport();
  4676. ImVec2 work_area_pos = viewport->GetWorkPos(); // Instead of using viewport->Pos we use GetWorkPos() to avoid menu bars, if any!
  4677. ImVec2 work_area_size = viewport->GetWorkSize();
  4678. ImVec2 window_pos = ImVec2((corner & 1) ? (work_area_pos.x + work_area_size.x - DISTANCE) : (work_area_pos.x + DISTANCE), (corner & 2) ? (work_area_pos.y + work_area_size.y - DISTANCE) : (work_area_pos.y + DISTANCE));
  4679. ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
  4680. ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
  4681. ImGui::SetNextWindowViewport(viewport->ID);
  4682. }
  4683. ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
  4684. if (ImGui::Begin("Example: Simple overlay", p_open, window_flags))
  4685. {
  4686. ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
  4687. ImGui::Separator();
  4688. if (ImGui::IsMousePosValid())
  4689. ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
  4690. else
  4691. ImGui::Text("Mouse Position: <invalid>");
  4692. if (ImGui::BeginPopupContextWindow())
  4693. {
  4694. if (ImGui::MenuItem("Custom", NULL, corner == -1)) corner = -1;
  4695. if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
  4696. if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
  4697. if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
  4698. if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
  4699. if (p_open && ImGui::MenuItem("Close")) *p_open = false;
  4700. ImGui::EndPopup();
  4701. }
  4702. }
  4703. ImGui::End();
  4704. }
  4705. //-----------------------------------------------------------------------------
  4706. // [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
  4707. //-----------------------------------------------------------------------------
  4708. // Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
  4709. // This apply to all regular items as well.
  4710. // Read FAQ section "How can I have multiple widgets with the same label?" for details.
  4711. static void ShowExampleAppWindowTitles(bool*)
  4712. {
  4713. // By default, Windows are uniquely identified by their title.
  4714. // You can use the "##" and "###" markers to manipulate the display/ID.
  4715. // Using "##" to display same title but have unique identifier.
  4716. ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
  4717. ImGui::Begin("Same title as another window##1");
  4718. ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
  4719. ImGui::End();
  4720. ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
  4721. ImGui::Begin("Same title as another window##2");
  4722. ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
  4723. ImGui::End();
  4724. // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
  4725. char buf[128];
  4726. sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
  4727. ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
  4728. ImGui::Begin(buf);
  4729. ImGui::Text("This window has a changing title.");
  4730. ImGui::End();
  4731. }
  4732. //-----------------------------------------------------------------------------
  4733. // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
  4734. //-----------------------------------------------------------------------------
  4735. // Demonstrate using the low-level ImDrawList to draw custom shapes.
  4736. static void ShowExampleAppCustomRendering(bool* p_open)
  4737. {
  4738. if (!ImGui::Begin("Example: Custom rendering", p_open))
  4739. {
  4740. ImGui::End();
  4741. return;
  4742. }
  4743. // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of
  4744. // overloaded operators, etc. Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your
  4745. // types and ImVec2/ImVec4. Dear ImGui defines overloaded operators but they are internal to imgui.cpp and not
  4746. // exposed outside (to avoid messing with your types) In this example we are not using the maths operators!
  4747. if (ImGui::BeginTabBar("##TabBar"))
  4748. {
  4749. if (ImGui::BeginTabItem("Primitives"))
  4750. {
  4751. ImGui::PushItemWidth(-ImGui::GetFontSize() * 10);
  4752. ImDrawList* draw_list = ImGui::GetWindowDrawList();
  4753. // Draw gradients
  4754. // (note that those are currently exacerbating our sRGB/Linear issues)
  4755. // Calling ImGui::GetColorU32() multiplies the given colors by the current Style Alpha, but you may pass the IM_COL32() directly as well..
  4756. ImGui::Text("Gradients");
  4757. ImVec2 gradient_size = ImVec2(ImGui::CalcItemWidth(), ImGui::GetFrameHeight());
  4758. {
  4759. ImVec2 p0 = ImGui::GetCursorScreenPos();
  4760. ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
  4761. ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 0, 0, 255));
  4762. ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 255, 255, 255));
  4763. draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
  4764. ImGui::InvisibleButton("##gradient1", gradient_size);
  4765. }
  4766. {
  4767. ImVec2 p0 = ImGui::GetCursorScreenPos();
  4768. ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
  4769. ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 255, 0, 255));
  4770. ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 0, 0, 255));
  4771. draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
  4772. ImGui::InvisibleButton("##gradient2", gradient_size);
  4773. }
  4774. // Draw a bunch of primitives
  4775. ImGui::Text("All primitives");
  4776. static float sz = 36.0f;
  4777. static float thickness = 3.0f;
  4778. static int ngon_sides = 6;
  4779. static bool circle_segments_override = false;
  4780. static int circle_segments_override_v = 12;
  4781. static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
  4782. ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
  4783. ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
  4784. ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12);
  4785. ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override);
  4786. ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
  4787. if (ImGui::SliderInt("Circle segments", &circle_segments_override_v, 3, 40))
  4788. circle_segments_override = true;
  4789. ImGui::ColorEdit4("Color", &colf.x);
  4790. const ImVec2 p = ImGui::GetCursorScreenPos();
  4791. const ImU32 col = ImColor(colf);
  4792. const float spacing = 10.0f;
  4793. const ImDrawCornerFlags corners_none = 0;
  4794. const ImDrawCornerFlags corners_all = ImDrawCornerFlags_All;
  4795. const ImDrawCornerFlags corners_tl_br = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight;
  4796. const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
  4797. float x = p.x + 4.0f;
  4798. float y = p.y + 4.0f;
  4799. for (int n = 0; n < 2; n++)
  4800. {
  4801. // First line uses a thickness of 1.0f, second line uses the configurable thickness
  4802. float th = (n == 0) ? 1.0f : thickness;
  4803. draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon
  4804. draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle
  4805. draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, corners_none, th); x += sz + spacing; // Square
  4806. draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_all, th); x += sz + spacing; // Square with all rounded corners
  4807. draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners
  4808. draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle
  4809. //draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle
  4810. draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
  4811. draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
  4812. draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line
  4813. draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x + sz*1.3f, y + sz*0.3f), ImVec2(x + sz - sz*1.3f, y + sz - sz*0.3f), ImVec2(x + sz, y + sz), col, th);
  4814. x = p.x + 4;
  4815. y += sz + spacing;
  4816. }
  4817. draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides); x += sz + spacing; // N-gon
  4818. draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments); x += sz + spacing; // Circle
  4819. draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col); x += sz + spacing; // Square
  4820. draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f); x += sz + spacing; // Square with all rounded corners
  4821. draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br); x += sz + spacing; // Square with two rounded corners
  4822. draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col); x += sz + spacing; // Triangle
  4823. //draw_list->AddTriangleFilled(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col); x += sz*0.4f + spacing; // Thin triangle
  4824. draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness)
  4825. draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness)
  4826. draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine)
  4827. draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255));
  4828. ImGui::Dummy(ImVec2((sz + spacing) * 8.8f, (sz + spacing) * 3.0f));
  4829. ImGui::PopItemWidth();
  4830. ImGui::EndTabItem();
  4831. }
  4832. if (ImGui::BeginTabItem("Canvas"))
  4833. {
  4834. static ImVector<ImVec2> points;
  4835. static ImVec2 scrolling(0.0f, 0.0f);
  4836. static bool opt_enable_grid = true;
  4837. static bool opt_enable_context_menu = true;
  4838. static bool adding_line = false;
  4839. ImGui::Checkbox("Enable grid", &opt_enable_grid);
  4840. ImGui::Checkbox("Enable context menu", &opt_enable_context_menu);
  4841. ImGui::Text("Mouse Left: drag to add lines,\nMouse Right: drag to scroll, click for context menu.");
  4842. // Typically you would use a BeginChild()/EndChild() pair to benefit from a clipping region + own scrolling.
  4843. // Here we demonstrate that this can be replaced by simple offsetting + custom drawing + PushClipRect/PopClipRect() calls.
  4844. // To use a child window instead we could use, e.g:
  4845. // ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Disable padding
  4846. // ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(50, 50, 50, 255)); // Set a background color
  4847. // ImGui::BeginChild("canvas", ImVec2(0.0f, 0.0f), true, ImGuiWindowFlags_NoMove);
  4848. // ImGui::PopStyleColor();
  4849. // ImGui::PopStyleVar();
  4850. // [...]
  4851. // ImGui::EndChild();
  4852. // Using InvisibleButton() as a convenience 1) it will advance the layout cursor and 2) allows us to use IsItemHovered()/IsItemActive()
  4853. ImVec2 canvas_p0 = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
  4854. ImVec2 canvas_sz = ImGui::GetContentRegionAvail(); // Resize canvas to what's available
  4855. if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f;
  4856. if (canvas_sz.y < 50.0f) canvas_sz.y = 50.0f;
  4857. ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
  4858. // Draw border and background color
  4859. ImGuiIO& io = ImGui::GetIO();
  4860. ImDrawList* draw_list = ImGui::GetWindowDrawList();
  4861. draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(50, 50, 50, 255));
  4862. draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255));
  4863. // This will catch our interactions
  4864. ImGui::InvisibleButton("canvas", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
  4865. const bool is_hovered = ImGui::IsItemHovered(); // Hovered
  4866. const bool is_active = ImGui::IsItemActive(); // Held
  4867. const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y); // Lock scrolled origin
  4868. const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
  4869. // Add first and second point
  4870. if (is_hovered && !adding_line && ImGui::IsMouseClicked(ImGuiMouseButton_Left))
  4871. {
  4872. points.push_back(mouse_pos_in_canvas);
  4873. points.push_back(mouse_pos_in_canvas);
  4874. adding_line = true;
  4875. }
  4876. if (adding_line)
  4877. {
  4878. points.back() = mouse_pos_in_canvas;
  4879. if (!ImGui::IsMouseDown(ImGuiMouseButton_Left))
  4880. adding_line = false;
  4881. }
  4882. // Pan (we use a zero mouse threshold when there's no context menu)
  4883. // You may decide to make that threshold dynamic based on whether the mouse is hovering something etc.
  4884. const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f;
  4885. if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan))
  4886. {
  4887. scrolling.x += io.MouseDelta.x;
  4888. scrolling.y += io.MouseDelta.y;
  4889. }
  4890. // Context menu (under default mouse threshold)
  4891. ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
  4892. if (opt_enable_context_menu && ImGui::IsMouseReleased(ImGuiMouseButton_Right) && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
  4893. ImGui::OpenPopupOnItemClick("context");
  4894. if (ImGui::BeginPopup("context"))
  4895. {
  4896. if (adding_line)
  4897. points.resize(points.size() - 2);
  4898. adding_line = false;
  4899. if (ImGui::MenuItem("Remove one", NULL, false, points.Size > 0)) { points.resize(points.size() - 2); }
  4900. if (ImGui::MenuItem("Remove all", NULL, false, points.Size > 0)) { points.clear(); }
  4901. ImGui::EndPopup();
  4902. }
  4903. // Draw grid + all lines in the canvas
  4904. draw_list->PushClipRect(canvas_p0, canvas_p1, true);
  4905. if (opt_enable_grid)
  4906. {
  4907. const float GRID_STEP = 64.0f;
  4908. for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP)
  4909. draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y), ImVec2(canvas_p0.x + x, canvas_p1.y), IM_COL32(200, 200, 200, 40));
  4910. for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP)
  4911. draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y), ImVec2(canvas_p1.x, canvas_p0.y + y), IM_COL32(200, 200, 200, 40));
  4912. }
  4913. for (int n = 0; n < points.Size; n += 2)
  4914. draw_list->AddLine(ImVec2(origin.x + points[n].x, origin.y + points[n].y), ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
  4915. draw_list->PopClipRect();
  4916. ImGui::EndTabItem();
  4917. }
  4918. if (ImGui::BeginTabItem("BG/FG draw lists"))
  4919. {
  4920. static bool draw_bg = true;
  4921. static bool draw_fg = true;
  4922. ImGui::Checkbox("Draw in Background draw list", &draw_bg);
  4923. ImGui::SameLine(); HelpMarker("The Background draw list will be rendered below every Dear ImGui windows.");
  4924. ImGui::Checkbox("Draw in Foreground draw list", &draw_fg);
  4925. ImGui::SameLine(); HelpMarker("The Foreground draw list will be rendered over every Dear ImGui windows.");
  4926. ImVec2 window_pos = ImGui::GetWindowPos();
  4927. ImVec2 window_size = ImGui::GetWindowSize();
  4928. ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f);
  4929. if (draw_bg)
  4930. ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10 + 4);
  4931. if (draw_fg)
  4932. ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 0, 10);
  4933. ImGui::EndTabItem();
  4934. }
  4935. ImGui::EndTabBar();
  4936. }
  4937. ImGui::End();
  4938. }
  4939. //-----------------------------------------------------------------------------
  4940. // [SECTION] Example App: Docking, DockSpace / ShowExampleAppDockSpace()
  4941. //-----------------------------------------------------------------------------
  4942. // Demonstrate using DockSpace() to create an explicit docking node within an existing window.
  4943. // Note that you dock windows into each others _without_ a dockspace, by just clicking on
  4944. // a window title bar and moving it (+ hold SHIFT if io.ConfigDockingWithShift is set).
  4945. // DockSpace() and DockSpaceOverViewport() are only useful to construct a central docking
  4946. // location for your application.
  4947. void ShowExampleAppDockSpace(bool* p_open)
  4948. {
  4949. // In 99% case you should be able to just call DockSpaceOverViewport() and ignore all the code below!
  4950. // In this specific demo, we are not using DockSpaceOverViewport() because:
  4951. // - we allow the host window to be floating/moveable instead of filling the viewport (when opt_fullscreen == false)
  4952. // - we allow the host window to have padding (when opt_padding == true)
  4953. // - we have a local menu bar in the host window (vs. you could use BeginMainMenuBar() + DockSpaceOverViewport() in your code!)
  4954. // TL;DR; this demo is more complicated than what you would normally use.
  4955. // If we removed all the options we are showcasing, this demo would become:
  4956. // void ShowExampleAppDockSpace()
  4957. // {
  4958. // ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
  4959. // }
  4960. static bool opt_fullscreen = true;
  4961. static bool opt_padding = false;
  4962. static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
  4963. // We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
  4964. // because it would be confusing to have two docking targets within each others.
  4965. ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
  4966. if (opt_fullscreen)
  4967. {
  4968. ImGuiViewport* viewport = ImGui::GetMainViewport();
  4969. ImGui::SetNextWindowPos(viewport->GetWorkPos());
  4970. ImGui::SetNextWindowSize(viewport->GetWorkSize());
  4971. ImGui::SetNextWindowViewport(viewport->ID);
  4972. ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
  4973. ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
  4974. window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
  4975. window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
  4976. }
  4977. else
  4978. {
  4979. dockspace_flags &= ~ImGuiDockNodeFlags_PassthruCentralNode;
  4980. }
  4981. // When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background
  4982. // and handle the pass-thru hole, so we ask Begin() to not render a background.
  4983. if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
  4984. window_flags |= ImGuiWindowFlags_NoBackground;
  4985. // Important: note that we proceed even if Begin() returns false (aka window is collapsed).
  4986. // This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
  4987. // all active windows docked into it will lose their parent and become undocked.
  4988. // We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
  4989. // any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
  4990. if (!opt_padding)
  4991. ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
  4992. ImGui::Begin("DockSpace Demo", p_open, window_flags);
  4993. if (!opt_padding)
  4994. ImGui::PopStyleVar();
  4995. if (opt_fullscreen)
  4996. ImGui::PopStyleVar(2);
  4997. // DockSpace
  4998. ImGuiIO& io = ImGui::GetIO();
  4999. if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
  5000. {
  5001. ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
  5002. ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
  5003. }
  5004. else
  5005. {
  5006. ShowDockingDisabledMessage();
  5007. }
  5008. if (ImGui::BeginMenuBar())
  5009. {
  5010. if (ImGui::BeginMenu("Options"))
  5011. {
  5012. // Disabling fullscreen would allow the window to be moved to the front of other windows,
  5013. // which we can't undo at the moment without finer window depth/z control.
  5014. ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen);
  5015. ImGui::MenuItem("Padding", NULL, &opt_padding);
  5016. ImGui::Separator();
  5017. if (ImGui::MenuItem("Flag: NoSplit", "", (dockspace_flags & ImGuiDockNodeFlags_NoSplit) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoSplit; }
  5018. if (ImGui::MenuItem("Flag: NoResize", "", (dockspace_flags & ImGuiDockNodeFlags_NoResize) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoResize; }
  5019. if (ImGui::MenuItem("Flag: NoDockingInCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingInCentralNode) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoDockingInCentralNode; }
  5020. if (ImGui::MenuItem("Flag: AutoHideTabBar", "", (dockspace_flags & ImGuiDockNodeFlags_AutoHideTabBar) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_AutoHideTabBar; }
  5021. if (ImGui::MenuItem("Flag: PassthruCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0, opt_fullscreen)) { dockspace_flags ^= ImGuiDockNodeFlags_PassthruCentralNode; }
  5022. ImGui::Separator();
  5023. if (ImGui::MenuItem("Close", NULL, false, p_open != NULL))
  5024. *p_open = false;
  5025. ImGui::EndMenu();
  5026. }
  5027. HelpMarker(
  5028. "When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n\n"
  5029. " > if io.ConfigDockingWithShift==false (default):" "\n"
  5030. " drag windows from title bar to dock" "\n"
  5031. " > if io.ConfigDockingWithShift==true:" "\n"
  5032. " drag windows from anywhere and hold Shift to dock" "\n\n"
  5033. "This demo app has nothing to do with it!" "\n\n"
  5034. "This demo app only demonstrate the use of ImGui::DockSpace() which allows you to manually create a docking node _within_ another window. This is useful so you can decorate your main application window (e.g. with a menu bar)." "\n\n"
  5035. "ImGui::DockSpace() comes with one hard constraint: it needs to be submitted _before_ any window which may be docked into it. Therefore, if you use a dock spot as the central point of your application, you'll probably want it to be part of the very first window you are submitting to imgui every frame." "\n\n"
  5036. "(NB: because of this constraint, the implicit \"Debug\" window can not be docked into an explicit DockSpace() node, because that window is submitted as part of the NewFrame() call. An easy workaround is that you can create your own implicit \"Debug##2\" window after calling DockSpace() and leave it in the window stack for anyone to use.)"
  5037. );
  5038. ImGui::EndMenuBar();
  5039. }
  5040. ImGui::End();
  5041. }
  5042. //-----------------------------------------------------------------------------
  5043. // [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
  5044. //-----------------------------------------------------------------------------
  5045. // Simplified structure to mimic a Document model
  5046. struct MyDocument
  5047. {
  5048. const char* Name; // Document title
  5049. bool Open; // Set when open (we keep an array of all available documents to simplify demo code!)
  5050. bool OpenPrev; // Copy of Open from last update.
  5051. bool Dirty; // Set when the document has been modified
  5052. bool WantClose; // Set when the document
  5053. ImVec4 Color; // An arbitrary variable associated to the document
  5054. MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
  5055. {
  5056. Name = name;
  5057. Open = OpenPrev = open;
  5058. Dirty = false;
  5059. WantClose = false;
  5060. Color = color;
  5061. }
  5062. void DoOpen() { Open = true; }
  5063. void DoQueueClose() { WantClose = true; }
  5064. void DoForceClose() { Open = false; Dirty = false; }
  5065. void DoSave() { Dirty = false; }
  5066. // Display placeholder contents for the Document
  5067. static void DisplayContents(MyDocument* doc)
  5068. {
  5069. ImGui::PushID(doc);
  5070. ImGui::Text("Document \"%s\"", doc->Name);
  5071. ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
  5072. ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
  5073. ImGui::PopStyleColor();
  5074. if (ImGui::Button("Modify", ImVec2(100, 0)))
  5075. doc->Dirty = true;
  5076. ImGui::SameLine();
  5077. if (ImGui::Button("Save", ImVec2(100, 0)))
  5078. doc->DoSave();
  5079. ImGui::ColorEdit3("color", &doc->Color.x); // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
  5080. ImGui::PopID();
  5081. }
  5082. // Display context menu for the Document
  5083. static void DisplayContextMenu(MyDocument* doc)
  5084. {
  5085. if (!ImGui::BeginPopupContextItem())
  5086. return;
  5087. char buf[256];
  5088. sprintf(buf, "Save %s", doc->Name);
  5089. if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open))
  5090. doc->DoSave();
  5091. if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open))
  5092. doc->DoQueueClose();
  5093. ImGui::EndPopup();
  5094. }
  5095. };
  5096. struct ExampleAppDocuments
  5097. {
  5098. ImVector<MyDocument> Documents;
  5099. ExampleAppDocuments()
  5100. {
  5101. Documents.push_back(MyDocument("Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
  5102. Documents.push_back(MyDocument("Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
  5103. Documents.push_back(MyDocument("Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
  5104. Documents.push_back(MyDocument("Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
  5105. Documents.push_back(MyDocument("A Rather Long Title", false));
  5106. Documents.push_back(MyDocument("Some Document", false));
  5107. }
  5108. };
  5109. // [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
  5110. // If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
  5111. // as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
  5112. // the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has
  5113. // disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
  5114. // give the impression of a flicker for one frame.
  5115. // We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
  5116. // Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
  5117. static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
  5118. {
  5119. for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
  5120. {
  5121. MyDocument* doc = &app.Documents[doc_n];
  5122. if (!doc->Open && doc->OpenPrev)
  5123. ImGui::SetTabItemClosed(doc->Name);
  5124. doc->OpenPrev = doc->Open;
  5125. }
  5126. }
  5127. void ShowExampleAppDocuments(bool* p_open)
  5128. {
  5129. static ExampleAppDocuments app;
  5130. // Options
  5131. enum Target
  5132. {
  5133. Target_None,
  5134. Target_Tab, // Create documents as local tab into a local tab bar
  5135. Target_DockSpaceAndWindow // Create documents as regular windows, and create an embedded dockspace
  5136. };
  5137. static Target opt_target = Target_Tab;
  5138. static bool opt_reorderable = true;
  5139. static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
  5140. // When (opt_target == Target_DockSpaceAndWindow) there is the possibily that one of our child Document window (e.g. "Eggplant")
  5141. // that we emit gets docked into the same spot as the parent window ("Example: Documents").
  5142. // This would create a problematic feedback loop because selecting the "Eggplant" tab would make the "Example: Documents" tab
  5143. // not visible, which in turn would stop submitting the "Eggplant" window.
  5144. // We avoid this problem by submitting our documents window even if our parent window is not currently visible.
  5145. // Another solution may be to make the "Example: Documents" window use the ImGuiWindowFlags_NoDocking.
  5146. bool window_contents_visible = ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar);
  5147. if (!window_contents_visible && opt_target != Target_DockSpaceAndWindow)
  5148. {
  5149. ImGui::End();
  5150. return;
  5151. }
  5152. // Menu
  5153. if (ImGui::BeginMenuBar())
  5154. {
  5155. if (ImGui::BeginMenu("File"))
  5156. {
  5157. int open_count = 0;
  5158. for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
  5159. open_count += app.Documents[doc_n].Open ? 1 : 0;
  5160. if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
  5161. {
  5162. for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
  5163. {
  5164. MyDocument* doc = &app.Documents[doc_n];
  5165. if (!doc->Open)
  5166. if (ImGui::MenuItem(doc->Name))
  5167. doc->DoOpen();
  5168. }
  5169. ImGui::EndMenu();
  5170. }
  5171. if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
  5172. for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
  5173. app.Documents[doc_n].DoQueueClose();
  5174. if (ImGui::MenuItem("Exit", "Alt+F4")) {}
  5175. ImGui::EndMenu();
  5176. }
  5177. ImGui::EndMenuBar();
  5178. }
  5179. // [Debug] List documents with one checkbox for each
  5180. for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
  5181. {
  5182. MyDocument* doc = &app.Documents[doc_n];
  5183. if (doc_n > 0)
  5184. ImGui::SameLine();
  5185. ImGui::PushID(doc);
  5186. if (ImGui::Checkbox(doc->Name, &doc->Open))
  5187. if (!doc->Open)
  5188. doc->DoForceClose();
  5189. ImGui::PopID();
  5190. }
  5191. ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
  5192. ImGui::Combo("Output", (int*)&opt_target, "None\0TabBar+Tabs\0DockSpace+Window\0");
  5193. ImGui::PopItemWidth();
  5194. bool redock_all = false;
  5195. if (opt_target == Target_Tab) { ImGui::SameLine(); ImGui::Checkbox("Reorderable Tabs", &opt_reorderable); }
  5196. if (opt_target == Target_DockSpaceAndWindow) { ImGui::SameLine(); redock_all = ImGui::Button("Redock all"); }
  5197. ImGui::Separator();
  5198. // Tabs
  5199. if (opt_target == Target_Tab)
  5200. {
  5201. ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
  5202. if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
  5203. {
  5204. if (opt_reorderable)
  5205. NotifyOfDocumentsClosedElsewhere(app);
  5206. // [DEBUG] Stress tests
  5207. //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1; // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
  5208. //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name); // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
  5209. // Submit Tabs
  5210. for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
  5211. {
  5212. MyDocument* doc = &app.Documents[doc_n];
  5213. if (!doc->Open)
  5214. continue;
  5215. ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
  5216. bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags);
  5217. // Cancel attempt to close when unsaved add to save queue so we can display a popup.
  5218. if (!doc->Open && doc->Dirty)
  5219. {
  5220. doc->Open = true;
  5221. doc->DoQueueClose();
  5222. }
  5223. MyDocument::DisplayContextMenu(doc);
  5224. if (visible)
  5225. {
  5226. MyDocument::DisplayContents(doc);
  5227. ImGui::EndTabItem();
  5228. }
  5229. }
  5230. ImGui::EndTabBar();
  5231. }
  5232. }
  5233. else if (opt_target == Target_DockSpaceAndWindow)
  5234. {
  5235. if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DockingEnable)
  5236. {
  5237. NotifyOfDocumentsClosedElsewhere(app);
  5238. // Create a DockSpace node where any window can be docked
  5239. ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
  5240. ImGui::DockSpace(dockspace_id);
  5241. // Create Windows
  5242. for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
  5243. {
  5244. MyDocument* doc = &app.Documents[doc_n];
  5245. if (!doc->Open)
  5246. continue;
  5247. ImGui::SetNextWindowDockID(dockspace_id, redock_all ? ImGuiCond_Always : ImGuiCond_FirstUseEver);
  5248. ImGuiWindowFlags window_flags = (doc->Dirty ? ImGuiWindowFlags_UnsavedDocument : 0);
  5249. bool visible = ImGui::Begin(doc->Name, &doc->Open, window_flags);
  5250. // Cancel attempt to close when unsaved add to save queue so we can display a popup.
  5251. if (!doc->Open && doc->Dirty)
  5252. {
  5253. doc->Open = true;
  5254. doc->DoQueueClose();
  5255. }
  5256. MyDocument::DisplayContextMenu(doc);
  5257. if (visible)
  5258. MyDocument::DisplayContents(doc);
  5259. ImGui::End();
  5260. }
  5261. }
  5262. else
  5263. {
  5264. ShowDockingDisabledMessage();
  5265. }
  5266. }
  5267. // Early out other contents
  5268. if (!window_contents_visible)
  5269. {
  5270. ImGui::End();
  5271. return;
  5272. }
  5273. // Update closing queue
  5274. static ImVector<MyDocument*> close_queue;
  5275. if (close_queue.empty())
  5276. {
  5277. // Close queue is locked once we started a popup
  5278. for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
  5279. {
  5280. MyDocument* doc = &app.Documents[doc_n];
  5281. if (doc->WantClose)
  5282. {
  5283. doc->WantClose = false;
  5284. close_queue.push_back(doc);
  5285. }
  5286. }
  5287. }
  5288. // Display closing confirmation UI
  5289. if (!close_queue.empty())
  5290. {
  5291. int close_queue_unsaved_documents = 0;
  5292. for (int n = 0; n < close_queue.Size; n++)
  5293. if (close_queue[n]->Dirty)
  5294. close_queue_unsaved_documents++;
  5295. if (close_queue_unsaved_documents == 0)
  5296. {
  5297. // Close documents when all are unsaved
  5298. for (int n = 0; n < close_queue.Size; n++)
  5299. close_queue[n]->DoForceClose();
  5300. close_queue.clear();
  5301. }
  5302. else
  5303. {
  5304. if (!ImGui::IsPopupOpen("Save?"))
  5305. ImGui::OpenPopup("Save?");
  5306. if (ImGui::BeginPopupModal("Save?"))
  5307. {
  5308. ImGui::Text("Save change to the following items?");
  5309. ImGui::SetNextItemWidth(-1.0f);
  5310. if (ImGui::ListBoxHeader("##", close_queue_unsaved_documents, 6))
  5311. {
  5312. for (int n = 0; n < close_queue.Size; n++)
  5313. if (close_queue[n]->Dirty)
  5314. ImGui::Text("%s", close_queue[n]->Name);
  5315. ImGui::ListBoxFooter();
  5316. }
  5317. if (ImGui::Button("Yes", ImVec2(80, 0)))
  5318. {
  5319. for (int n = 0; n < close_queue.Size; n++)
  5320. {
  5321. if (close_queue[n]->Dirty)
  5322. close_queue[n]->DoSave();
  5323. close_queue[n]->DoForceClose();
  5324. }
  5325. close_queue.clear();
  5326. ImGui::CloseCurrentPopup();
  5327. }
  5328. ImGui::SameLine();
  5329. if (ImGui::Button("No", ImVec2(80, 0)))
  5330. {
  5331. for (int n = 0; n < close_queue.Size; n++)
  5332. close_queue[n]->DoForceClose();
  5333. close_queue.clear();
  5334. ImGui::CloseCurrentPopup();
  5335. }
  5336. ImGui::SameLine();
  5337. if (ImGui::Button("Cancel", ImVec2(80, 0)))
  5338. {
  5339. close_queue.clear();
  5340. ImGui::CloseCurrentPopup();
  5341. }
  5342. ImGui::EndPopup();
  5343. }
  5344. }
  5345. }
  5346. ImGui::End();
  5347. }
  5348. // End of Demo code
  5349. #else
  5350. void ImGui::ShowAboutWindow(bool*) {}
  5351. void ImGui::ShowDemoWindow(bool*) {}
  5352. void ImGui::ShowUserGuide() {}
  5353. void ImGui::ShowStyleEditor(ImGuiStyle*) {}
  5354. #endif
  5355. #endif // #ifndef IMGUI_DISABLE