123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406 |
- ' Copyright (c) 2006-2020 Bruce A Henderson
- '
- ' Permission is hereby granted, free of charge, to any person obtaining a copy
- ' of this software and associated documentation files (the "Software"), to deal
- ' in the Software without restriction, including without limitation the rights
- ' to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- ' copies of the Software, and to permit persons to whom the Software is
- ' furnished to do so, subject to the following conditions:
- '
- ' The above copyright notice and this permission notice shall be included in
- ' all copies or substantial portions of the Software.
- '
- ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- ' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- ' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- ' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- ' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- ' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- ' THE SOFTWARE.
- '
- SuperStrict
- Import "gtkcommon.bmx"
- Type TGTKGadget Extends TGadget
- Field iclass:Int
- ' usually the pointer to the gtk widget
- Field handle:Byte Ptr
- Field menubar:Byte Ptr
- Field menu:Byte Ptr
- ' reference to this gadgets' font (if we've ever set it programmatically)
- Field _font:TGuiFont
- ' a map to hold connection handler ids... sometimes we need to disconnect the little buggers.
- Field connectionMap:TMap = New TMap
- ' a unique identifier for this gadget
- Field accelMapId:String
- Field accelString:String
- Field hasAccel:Int
-
- Field initialSizing:Int = False
- Field mySetVisible:Int = True
- Field visible:Int = False
-
- ' the class id of this gadget in MaxGUI terms.
- Field maxguiClass:Int
-
- Method Init(GadgetClass:Int, _x:Int, _y:Int, _w:Int, _h:Int, _style:Int)
- SetRect(_x,_y,_w,_h)
- iclass = GadgetClass
- kids = New TList
- style = _style
- End Method
- Method addConnection(name:String, id:Int)
- connectionMap.Insert(name, TGTKInteger.Set(id))
- End Method
- Function Destroy(data:Byte Ptr, closure:Byte Ptr)
- 'Print "Destroy Handler"
- End Function
- Function Create:TGTKGadget(GadgetClass:Int, x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int, mgclass:Int)
- Local gadget:TGTKGadget
-
- Select GadgetClass
- Case GTK_WINDOW
- gadget = TGTKWindow.CreateWindow(x, y ,w , h, label, group, style)
- Case GTK_BUTTON
- gadget = TGTKButtonPush.CreateButton(x, y ,w , h, label, group, style)
- Case GTK_RADIOBUTTON
- gadget = TGTKButtonRadio.CreateButton(x, y ,w , h, label, group, style)
- Case GTK_CHECKBUTTON
- gadget = TGTKButtonCheckbox.CreateButton(x, y ,w , h, label, group, style)
- Case GTK_LABEL
- gadget = TGTKLabel.CreateLabel(x, y ,w , h, label, group, style)
- Case GTK_MENUITEM
- gadget = TGTKMenuItem.CreateMenuItem(label, style, group)
- Case GTK_TEXTFIELD
- gadget = TGTKTextField.CreateTextField(x, y ,w , h, label, group, style)
- Case GTK_HTMLVIEW
- If gtk3maxgui_htmlview Then
- gadget = gtk3maxgui_htmlview.CreateHTMLView(x, y ,w , h, label, group, style)
- Else
- Throw "No HTMLView specified. You need To Import one! " + ..
- " Import Gtk.gtk3webkitgtk"
- End If
- Case GTK_TABBER
- gadget = TGTKTabber.CreateTabber(x, y ,w , h, label, group, style)
- Case GTK_PANEL
- gadget = TGTKPanel.CreatePanel(x, y ,w , h, label, group, style)
- Case GTK_COMBOBOX
- gadget = TGTKComboBox.CreateComboBox(x, y ,w , h, label, group, style)
- Case GTK_PROGRESSBAR
- gadget = TGTKProgressBar.CreateProgressBar(x, y ,w , h, label, group, style)
- Case GTK_STEPPER
- gadget = TGTKStepper.CreateStepper(x, y ,w , h, label, group, style)
- Case GTK_SCROLLBAR
- gadget = TGTKScrollBar.CreateScrollBar(x, y ,w , h, label, group, style)
- Case GTK_TRACKBAR
- gadget = TGTKTrackBar.CreateTrackBar(x, y ,w , h, label, group, style)
- Case GTK_TEXTAREA
- ' no custom text area? use the default
- If Not gtk3maxgui_textarea Then
- gtk3maxgui_textarea = New TGTKDefaultTextAreaDriver
- End If
- gadget = gtk3maxgui_textarea.CreateTextArea(x, y ,w , h, label, group, style)
- Case GTK_TOOLBAR
- gadget = TGTKToolbar.CreateToolBar(x, y ,w , h, label, group, style)
- Case GTK_LISTBOX
- gadget = TGTKListbox.CreateListBox(x, y ,w , h, label, group, style)
- Case GTK_TREEVIEW
- gadget = TGTKTreeView.CreateTreeView(x, y ,w , h, label, group, style)
- Case GTK_CANVAS
- gadget = TGTKCanvas.CreateCanvas(x, y ,w , h, label, group, style)
- End Select
- ' map the new gadget - so we can find it later if required
- If gadget Then
- GadgetMap.Insert(gadget.handle, gadget)
- End If
-
- If group Then
- gadget._SetParent group
- End If
- gadget.SetShape x,y,w,h
- ' set the maxgui class type
- gadget.maxguiClass = mgclass
- Return gadget
- End Function
- Method Free:Int()
- Local gadget:TGTKGadget
- Local rkids:TList
- rkids=kids.Reversed()
- For gadget = EachIn rkids
- gadget.Free()
- Next
- gadget = TGTKGadget(parent)
- If gadget Then
- gadget.kids.remove Self
- End If
- ' remove reference from global reference map
- If handle Then
- GadgetMap.Remove(handle)
- handle = Null
- End If
-
- connectionMap.Clear()
-
- End Method
- Rem
- bbdoc: Show or hide the gadget.
- End Rem
- Method SetShow:Int(truefalse:Int)
- visible = truefalse
- mySetVisible = visible
-
- If truefalse Then
- gtk_widget_show(handle)
- Else
- gtk_widget_hide(handle)
- EndIf
-
- UpdateChildVisibility()
- End Method
- Method UpdateChildVisibility()
- For Local gadget:TGTKGadget = EachIn kids
- If Not visible Then
- gadget.visible = False
- Else
- gadget.visible = gadget.mySetVisible
- End If
-
- gadget.UpdateChildVisibility()
- Next
- End Method
- ' checks text for mnemonics
- Method processText:String(txt:String)
- ' convert underscores to doubles
- txt = txt.Replace("_", "__")
- txt = txt.Replace("&&", "$^^$")
- txt = txt.Replace("&", "_")
- txt = txt.Replace("$^^$", "&")
-
- Return txt
- End Method
- Method setAccelEntry(keycode:Int, modifier:Int)
- Local accelKey:Int
- Local modKey:Int
-
- If accelString And hasAccel Then
- Local accelPtr:Byte Ptr = accelString.ToUTF8String()
- gtk_accelerator_parse(accelPtr, Varptr accelKey, Varptr modKey)
- MemFree(accelPtr)
- If accelKey <> 0 Then
- gtk_widget_remove_accelerator(handle, getWindow().accelGroup, accelKey, modKey)
- hasAccel = False
- End If
- End If
- ' enabling accelerator?
- If keycode Then
- accelString = TGTKKeyMap.accelToString(keycode, modifier)
- Local accelPtr:Byte Ptr = accelString.ToUTF8String()
- gtk_accelerator_parse(accelPtr, Varptr accelKey, Varptr modKey)
- MemFree(accelPtr)
- gtk_widget_add_accelerator(handle, "activate", getWindow().accelGroup, accelKey, modKey, GTK_ACCEL_VISIBLE)
- hasAccel = True
- End If
- End Method
-
- Method setAccelMapId(id:String)
- accelMapId = id.Replace("&", "")
- End Method
- ' returns the widgets window
- Method getWindow:TGTKWindow()
- If Not TGTKWindow(Self) Then
- If TGTKGadget(parent) Then
- Return TGTKGadget(parent).getWindow()
- Else
- Return Null
- End If
- End If
-
- Return TGTKWindow(Self)
- End Method
- Rem
- bbdoc: Callback for focus lost.
- End Rem
- Function OnFocusLost:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- PostGuiEvent(EVENT_GADGETLOSTFOCUS, TGadget(obj))
- End Function
-
- Rem
- bbdoc: Set the gadget tooltip.
- End Rem
- Method setToolTip:Int(tip:String)
- If tip And tip.length > 0 Then
- Local tipPtr:Byte Ptr = tip.ToUTF8String()
- gtk_widget_set_tooltip_text(handle, tipPtr)
- MemFree(tipPtr)
- Else
- gtk_widget_set_has_tooltip(handle, False)
- End If
- End Method
- Rem
- bbdoc: Perform an activation command on the gadget.
- End Rem
- Method Activate:Int(cmd:Int)
- Select cmd
- Case ACTIVATE_FOCUS
- gtk_widget_grab_focus(handle)
- Case ACTIVATE_FORWARD
- Case ACTIVATE_BACK
- Case ACTIVATE_REDRAW
- redraw()
- PostGuiEvent(EVENT_GADGETPAINT, Self)
- End Select
- End Method
-
- Method redraw()
- gtk_widget_queue_draw(handle)
- End Method
- Rem
- bbdoc: Return the gadget's client width.
- End Rem
- Method ClientWidth:Int()
- If initialSizing Then
- ?bmxng
- Local minReq:GtkRequisition
- Local natReq:GtkRequisition
- ?Not bmxng
- Local minReq:GtkRequisition = New GtkRequisition
- Local natReq:GtkRequisition = New GtkRequisition
- ?
- gtk_widget_get_preferred_size(handle, minReq, natReq)
- Return natReq.width
- End If
- Return width
- End Method
- Rem
- bbdoc: Return the gadget's client height.
- End Rem
- Method ClientHeight:Int()
- If initialSizing Then
- ?bmxng
- Local minReq:GtkRequisition
- Local natReq:GtkRequisition
- ?Not bmxng
- Local minReq:GtkRequisition = New GtkRequisition
- Local natReq:GtkRequisition = New GtkRequisition
- ?
- gtk_widget_get_preferred_size(handle, minReq, natReq)
- Return natReq.height
- End If
- Return height
- End Method
- Method Rethink:Int()
- If handle
- gtk_layout_move(TGTKContainer(parent).container, handle, Max(xpos,0), Max(ypos,0))
- gtk_widget_set_size_request(handle, Max(width,0), Max(height,0))
- End If
- End Method
- Rem
- bbdoc: Return the gadget state.
- End Rem
- Method State:Int()
- Local flags:Int
- Local _state:Int = gtk_widget_get_state_flags(handle)
- Select _state
- Case GTK_STATE_FLAG_INSENSITIVE
- flags:| STATE_DISABLED
- Case GTK_STATE_FLAG_SELECTED
- flags:| STATE_SELECTED
- Case GTK_STATE_FLAG_ACTIVE
- flags:| STATE_ACTIVE
- End Select
- If Not gtk_widget_get_visible(handle) Then
- flags:| STATE_HIDDEN
- End If
- Return flags
- End Method
- End Type
- Rem
- bbdoc: The Desktop.
- End Rem
- Type TGTKDesktop Extends TGTKGadget
- Function CreateDesktop:TGTKDesktop()
- Local this:TGTKDesktop = New TGTKDesktop
- this.initDesktop()
- Return this
- End Function
- Method initDesktop()
- iclass = GTK_DESKTOP
- handle = gdk_screen_get_default()
- SetArea(0, 0, gdk_screen_get_width(handle), gdk_screen_get_height(handle))
- End Method
- Method Rethink:Int()
- End Method
- Rem
- bbdoc: Returns the desktop width.
- End Rem
- Method ClientWidth:Int()
- Return width
- End Method
- Rem
- bbdoc: Returns the desktop height.
- End Rem
- Method ClientHeight:Int()
- Return height
- End Method
-
- Rem
- bbdoc: Returns the desktop depth.
- End Rem
- Method GetDepth:Int()
- Local visual:Byte Ptr = gdk_screen_get_system_visual(handle)
- Return gdk_visual_get_depth(visual)
- End Method
-
- Rem
- bbdoc: Returns the desktop hertz.
- End Rem
- Method GetHertz:Int()
- Return bmx_gtk3_gtkdesktop_gethertz()
- End Method
-
- Rem
- bbdoc: Returns the desktop scale factor that maps from window coordiantes to the actual device pixels.
- about: On traditional systems this is 1, but on very high density outputs this can be a higher value (often 2).
- End Rem
- Method ScaleFactor:Int()
- Return gdk_screen_get_monitor_scale_factor(handle, 0)
- End Method
- End Type
- Rem
- bbdoc: This type handles "internal" widget containers for "Container" gadgets.
- End Rem
- Type TGTKContainer Extends TGTKGadget
- ' a multi-row container
- Field box:Byte Ptr
- ' the "Fixed" container that we place gadgets onto
- Field container:Byte Ptr
- ' dont need to free this, as removing radio buttons from it will free itself when empty
- Field radioGroup:Byte Ptr
-
- ' initialize the container stuff
- Method Init(GadgetClass:Int, x:Int, y:Int, w:Int, h:Int, style:Int)
- Super.init(GadgetClass, x, y, w, h, style)
- End Method
- Method ClientWidth:Int()
- Return width
- End Method
- Method ClientHeight:Int()
- Return height
- End Method
- End Type
- Rem
- bbdoc: A Window
- End Rem
- Type TGTKWindow Extends TGTKContainer
- Field statusbar:Byte Ptr
- Field sblabels:Byte Ptr[]
-
- Field toolbar:TGTKToolbar
- Field accelGroup:Byte Ptr
- Field oldCW:Int
- Field oldCH:Int
-
- Field _maximized:Int
- Field _minimized:Int
-
- Field ignoreMoveEvent:Int
- Field ignoreSizeEvent:Int
-
- Function CreateWindow:TGTKWindow(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKWindow = New TGTKWindow
- this.initWindow(x, y, w, h, label, group, style)
- gtkWindows.addLast(this)
-
- Return this
- End Function
- Method initWindow(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- If group And TGTKDesktop(group)
- group = Null
- End If
-
- ' should only be a window parent!!
- If group Then
- Assert TGTKWindow(group), "group not TGTKWindow!"
- End If
- handle = gtk_window_new(GTK_WINDOW_TOPLEVEL)
- Init(GTK_WINDOW, x, y, w, h, style)
- ' container BEGIN
- box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0)
- gtk_widget_show(box)
- If style & WINDOW_MENU Then
- menubar = gtk_menu_bar_new()
- gtk_box_pack_start(box, menubar, False, True, 0)
- gtk_widget_show(menubar)
- End If
- container = gtk_layout_new(Null, Null)
-
- gtk_widget_show(container)
- gtk_box_pack_start(box, container, True, True, 0)
- ' container END
- If style & WINDOW_STATUS Then
- createStatusbar()
- SetStatusText("")
- EndIf
- If (LocalizationMode() & LOCALIZATION_OVERRIDE) Then
- LocalizeGadget(Self, label)
- Else
- SetText(label)
- EndIf
- gtk_window_move(handle, x, y)
- gtk_window_set_default_size(handle, w, calcHeight(h))
- gtk_window_set_decorated(handle, (style & WINDOW_TITLEBAR))
- gtk_window_set_resizable(handle, (style & WINDOW_RESIZABLE))
-
- If style & WINDOW_TOOL Then
- gtk_window_set_type_hint(handle, GDK_WINDOW_TYPE_HINT_UTILITY)
- End If
- gtk_container_add(handle, box)
- ' some funky window setting up...
- ' It's all rather fiddly, but it appears to work.
- ?bmxng
- Local geom:GdkGeometry
- ?Not bmxng
- Local geom:GdkGeometry = New GdkGeometry
- ?
- 'DebugStop
- Local hints:Int = 0
- If style & WINDOW_RESIZABLE Then
- hints:| GDK_HINT_USER_SIZE
- geom.minWidth = 16
- geom.minHeight = 16
-
- hints:| GDK_HINT_RESIZE_INC
- geom.widthInc = 1
- geom.heightInc = 1
- Else
- geom.minWidth = w
- geom.minHeight = calcHeight(h)
- End If
- geom.maxWidth = -1
- geom.maxHeight = -1
- If Not (style & WINDOW_CLIENTCOORDS) Then
- geom.baseWidth = w
- geom.baseHeight = calcHeight(h)
- Else
- geom.baseWidth = -1
- geom.baseHeight = -1
- End If
- gtk_window_set_geometry_hints(handle, box, geom, GDK_HINT_POS | GDK_HINT_MIN_SIZE | ..
- GDK_HINT_BASE_SIZE | GDK_HINT_USER_POS | hints)
- If Not(style & WINDOW_RESIZABLE) Then
- gtk_widget_set_size_request(handle, w, calcHeight(h))
- End If
- ' connect this window with its parent
- If group And (style & WINDOW_CHILD) Then
- gtk_window_set_transient_for(handle, TGTKWindow(group).handle)
- End If
- Rem
- A Window produces the following events:
- EVENT_WINDOWMOVE Window has been moved
- EVENT_WINDOWSIZE Window has been resized
- EVENT_WINDOWCLOSE Window close icon clicked
- EVENT_WINDOWACTIVATE Window activated
- EVENT_WINDOWACCEPT Drag and Drop operation was attempted
- End Rem
- ' move
- addConnection("configure-event", g_signal_cb3(handle, "configure-event", OnWindowMoveSize, Self, Destroy, 0))
- ' size
- addConnection("check-resize", g_signal_cb2(handle, "check-resize", OnWindowSize, Self, Destroy, 0))
- ' close
- addConnection("delete-event", g_signal_cb3_ret(handle, "delete-event", OnWindowClose, Self, Destroy, 0))
- ' activate
- addConnection("focus-in-event", g_signal_cb3(handle, "focus-in-event", OnWindowActivate, Self, Destroy, 0))
- addConnection("focus-out-event", g_signal_cb3_ret(handle, "focus-out-event", OnWindowDeactivate, Self, Destroy, 0))
- ' accept
- 'g_signal_cb3(handle, "XXXXXX", WindowAccept, Self, Destroy, 0)
- ' minimize / maximize
- addConnection("window-state-event", g_signal_cb3_ret(handle, "window-state-event", OnWindowStateChange, Self, Destroy, 0))
- If style & WINDOW_ACCEPTFILES Then
- 'Local entries:Byte Ptr
-
- gtk_drag_dest_set(handle, GTK_DEST_DEFAULT_ALL, Null, 0, GDK_ACTION_COPY)
- gtk_drag_dest_add_uri_targets(handle)
-
- addConnection("drag-drop", g_signal_cb8(handle, "drag-data-received", OnDragDrop, Self, Destroy, 0))
- End If
-
- ' used for tabbers - ensure they are redrawn properly when required
- 'g_signal_cb7(container, "draw-background", OnDraw, Self, Destroy, 0)
- accelGroup = gtk_accel_group_new()
- gtk_window_add_accel_group(handle, accelGroup)
- setAccelMapId(label)
- If ~style & WINDOW_HIDDEN
- Setshow(True)
- Else
- SetShow(False)
- End If
- End Method
- Method calcHeight:Int(requestedHeight:Int)
- If Not (style & WINDOW_CLIENTCOORDS) Then
- Return requestedHeight
- Else
- ?bmxng
- Local minReq:GtkRequisition
- Local natReq:GtkRequisition
- ?Not bmxng
- Local minReq:GtkRequisition = New GtkRequisition
- Local natReq:GtkRequisition = New GtkRequisition
- ?
- If statusbar Then
- gtk_widget_get_preferred_size(statusbar, minReq, natReq)
- requestedHeight:+ natReq.height
- End If
- If menubar Then
- gtk_widget_get_preferred_size(menubar, minReq, natReq)
- requestedHeight:+ natReq.height
- End If
-
- Return requestedHeight
- End If
- End Method
- Method deCalcHeight:Int(actualHeight:Int)
- If Not (style & WINDOW_CLIENTCOORDS) Then
- Return actualHeight
- Else
- ?bmxng
- Local minReq:GtkRequisition
- Local natReq:GtkRequisition
- ?Not bmxng
- Local minReq:GtkRequisition = New GtkRequisition
- Local natReq:GtkRequisition = New GtkRequisition
- ?
- If statusbar Then
- gtk_widget_get_preferred_size(statusbar, minReq, natReq)
- actualHeight:- natReq.height
- End If
- If menubar Then
- gtk_widget_get_preferred_size(statusbar, minReq, natReq)
- actualHeight:- natReq.height
- End If
- Return actualHeight
- End If
- End Method
-
- Rem
- bbdoc: Callback for window size / move
- End Rem
- Function OnWindowMoveSize(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Int, y:Int, w:Int, h:Int
- bmx_gtk3maxgui_gdkeventconfigure(event, Varptr x, Varptr y, Varptr w, Varptr h)
- Local win:TGTKWindow = TGTKWindow(obj)
- If win Then
- Local change:Int = False
-
- h = win.deCalcHeight(h)
-
- ' Has the window actually changed size/position?
- If win.width <> w Or win.height <> h Then
- change = True
- If Not win.ignoreSizeEvent Then
- PostGuiEvent(EVENT_WINDOWSIZE, TGadget(obj),,,w,h)
- End If
- End If
-
- gtk_window_get_position(win.handle, Varptr x, Varptr y)
-
- If win.xpos <> x Or win.ypos <> y Then
- change = True
- If Not win.ignoreMoveEvent Then
- PostGuiEvent(EVENT_WINDOWMOVE, TGadget(obj),,,x,y)
- End If
- End If
- If win.ClientHeight() <> win.oldCH Or win.ClientWidth() <> win.oldCW Then
- win.oldCH = win.ClientHeight()
- win.oldCW = win.ClientWidth()
- change = True
- End If
-
- ' something has changed.. we need to update ourself and tell the children.
- If change Then
- win.setRect(x, y, w, h)
- win.layoutkids()
- End If
-
- win.ignoreMoveEvent = False
- win.ignoreSizeEvent = False
- End If
- End Function
-
- Method Rethink:Int()
- If style & WINDOW_RESIZABLE Then
- gtk_window_resize(handle, width, calcHeight(height))
- Else
- gtk_window_set_default_size(handle, width, calcHeight(height))
- End If
-
- layoutkids() ' we need to do this so the children know we've really changed.
- End Method
- Rem
- bbdoc: Callback for window size.
- about: This event doesn't actually trigger a max size event, but we use it to adjust the client
- size.
- End Rem
- Function OnWindowSize(widget:Byte Ptr, obj:Object)
- Local win:TGTKWindow = TGTKWindow(obj)
- If win Then
- If win.ClientHeight() <> win.oldCH Or win.ClientWidth() <> win.oldCW Then
- win.oldCH = win.ClientHeight()
- win.oldCW = win.ClientWidth()
- TGTKContainer(obj).rethink()
- End If
- End If
- End Function
- Rem
- bbdoc: Callback for window state change.
- End Rem
- Function OnWindowStateChange:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local statemask:Int
- bmx_gtk3maxgui_gdkeventwindowstate(event, Varptr statemask)
-
- Local win:TGTKWindow = TGTKWindow(obj)
- If win Then
- If statemask & GDK_WINDOW_STATE_ICONIFIED Then
- win._minimized = Not win._minimized
- End If
-
- If statemask & GDK_WINDOW_STATE_MAXIMIZED Then
- win._maximized = Not win._maximized
-
- ' when maximized, we can't be minimized... so clear it
- If win._maximized Then
- win._minimized = False
- End If
- End If
- End If
- End Function
- Rem
- bbdoc: Callback for window close
- End Rem
- Function OnWindowClose:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- PostGuiEvent(EVENT_WINDOWCLOSE, TGadget(obj))
- Return True ' we don't want it to close - that's a user decision :-p
- End Function
-
- Rem
- bbdoc: Callback for window activate
- End Rem
- Function OnWindowActivate(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- PostGuiEvent(EVENT_WINDOWACTIVATE, TGadget(obj))
- End Function
- Rem
- bbdoc: Callback for window deactivate
- about: Not used, but might come in handy at some point...
- End Rem
- Function OnWindowDeactivate:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- ' We catch this but don't act on it...
- Return False
- End Function
-
- Function OnDragDrop(widget:Byte Ptr, context:Byte Ptr, x:Int, y:Int, data:Byte Ptr, info:Int, time:Int, obj:Object)
- Local uris:String[] = bmx_gtk3_selection_data_get_uris(data)
- If uris Then
- For Local uri:String = EachIn uris
- PostGuiEvent EVENT_WINDOWACCEPT,TGadget(obj),0,0,x,y,uri.Replace("file://", "")
- Next
- End If
- End Function
- Method SetShape:Int(x:Int,y:Int,w:Int,h:Int)
- If x <> xpos Or y <> ypos Then
- ignoreMoveEvent = True
- End If
- If w <> width Or h <> height Then
- ignoreSizeEvent = True
- End If
- Super.SetShape(Max(x, 0), Max(y, 0), w, h)
- 'actually move/resize
- 'using the ignore* saves from backupping old position
- 'and sizes before calling "SetShape()"
- If ignoreMoveEvent Then
- gtk_window_move(handle, x, y)
- End If
- If ignoreSizeEvent Then
- gtk_window_resize(handle, w, h)
- End If
- End Method
- Rem
- bbdoc: Set the window status text
- End Rem
- Method SetStatusText:Int(text:String)
- If statusbar Then
- Local t:Int, m0:String, m1:String, m2:String
- m0 = text
- t = m0.find("~t")
- If t <> -1 Then
- m1 = m0[t+1..]
- m0 = m0[..t]
- End If
- t = m1.find("~t")
- If t <> -1 Then
- m2 = m1[t+1..]
- m1 = m1[..t]
- End If
-
- Local mb0:Byte Ptr = m0.ToUTF8String()
- Local mb1:Byte Ptr = m1.ToUTF8String()
- Local mb2:Byte Ptr = m2.ToUTF8String()
- gtk_label_set_text(sblabels[0], mb0)
- gtk_label_set_text(sblabels[1], mb1)
- gtk_label_set_text(sblabels[2], mb2)
- MemFree(mb2)
- MemFree(mb1)
- MemFree(mb0)
- If m0.length = 0 And m1.length = 0 And m2.length = 0 Then
- gtk_widget_show(sblabels[0])
- gtk_widget_hide(sblabels[1])
- gtk_widget_hide(sblabels[2])
- Else
- If m0.length > 0 Then
- gtk_widget_show(sblabels[0])
- Else
- gtk_widget_hide(sblabels[0])
- End If
-
- If m1.length > 0 Then
- gtk_widget_show(sblabels[1])
- Else
- gtk_widget_hide(sblabels[1])
- End If
-
- If m2.length > 0 Then
- gtk_widget_show(sblabels[2])
- Else
- gtk_widget_hide(sblabels[2])
- End If
- End If
- End If
- End Method
- Method GetMenu:TGadget()
- Return Self
- End Method
-
- Method createStatusbar()
- ' our "statusbar" is actually a horizontal box...
- statusbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)
- gtk_widget_show(statusbar)
- sblabels = New Byte Ptr[3]
-
- For Local i:Int = 0 Until 3
-
- Local sblabel:Byte Ptr = gtk_label_new("")
- sblabels[i] = sblabel
-
- If i = 0 Then
- gtk_misc_set_alignment(sblabel, 0, 0.5)
- 'gtk_label_set_yalign(sblabel, 0.5) ' 3.16
- Else If i = 2 Then
- gtk_misc_set_alignment(sblabel, 1, 0.5)
- 'gtk_label_set_xalign(sblabel, 1) ' 3.16
- 'gtk_label_set_yalign(sblabel, 0.5) ' 3.16
- End If
-
- gtk_box_pack_start(statusbar, sblabel, True, True, 0)
- Next
-
- ' add to the window!
- gtk_box_pack_start(box, statusbar, False, True, 0)
- End Method
- Method addToolbar(_toolbar:TGTKToolbar)
- If toolbar <> Null Then
- toolbar.free()
- End If
- toolbar = _toolbar
- ' add to the list
- gtk_box_pack_start(box, toolbar.handle, False, False, 0)
- ' we need to move this to the correct place (usually under the menu)
- If menubar Then
- gtk_box_reorder_child(box, toolbar.handle, 1)
- Else
- gtk_box_reorder_child(box, toolbar.handle, 0)
- End If
- End Method
- Method ClientHeight:Int()
- ?bmxng
- Local allocation:GtkAllocation
- ?Not bmxng
- Local allocation:GtkAllocation = New GtkAllocation
- ?
- gtk_widget_get_allocation(container, allocation)
- Local h:Int = allocation.height
- If h <= 8 Then
- h = height
- ?bmxng
- Local minReq:GtkRequisition
- Local natReq:GtkRequisition
- ?Not bmxng
- Local minReq:GtkRequisition = New GtkRequisition
- Local natReq:GtkRequisition = New GtkRequisition
- ?
- If statusbar Then
- gtk_widget_get_preferred_size(statusbar, minReq, natReq)
- h:- natReq.height
- End If
- If menubar Then
- gtk_widget_get_preferred_size(menubar, minReq, natReq)
- h:- natReq.height
- End If
- End If
- If toolbar Then
- h:- toolbar.height
- End If
-
- Return h
- End Method
- Method ClientWidth:Int()
- ?bmxng
- Local allocation:GtkAllocation
- ?Not bmxng
- Local allocation:GtkAllocation = New GtkAllocation
- ?
- gtk_widget_get_allocation(handle, allocation)
- Local w:Int = allocation.width
- If w <= 8 Then
- w = width
- End If
- Return w
- End Method
- Rem
- bbdoc: Pop up a popup menu
- End Rem
- Method PopupMenu:Int(menu:TGadget,extra:Object=Null)
- If TGTKMenuItem(menu) Then
- If TGTKMenuItem(menu).popupMenu Then
- TGTKMenuItem(menu).popupExtra = extra
- gtk_menu_popup(TGTKMenuItem(menu).popupMenu, Null, Null, Null, Null, 0, gtk_get_current_event_time())
- End If
- End If
- End Method
- Method free:Int() Override
- Super.Free()
- If handle
- gtk_widget_destroy(handle)
- EndIf
- handle = Null
- gtkWindows.remove(Self)
- End Method
- Method Activate:Int(cmd:Int)
- Super.Activate(cmd)
-
- If Not visible Return 0
- Select cmd
- Case ACTIVATE_MAXIMIZE
- gtk_window_maximize(handle)
- Case ACTIVATE_MINIMIZE
- gtk_window_iconify(handle)
- Case ACTIVATE_RESTORE
- ' since we need to remember if we are maximized while being minimized
- ' we check for minimized first...
- If _minimized Then
- gtk_window_deiconify(handle)
- Else If _maximized Then
- gtk_window_unmaximize(handle)
- End If
- Case ACTIVATE_FOCUS
- gtk_window_present(handle)
- End Select
- End Method
-
- Method SetMinimumSize:Int(w:Int, h:Int)
- ?bmxng
- Local geom:GdkGeometry
- ?Not bmxng
- Local geom:GdkGeometry = New GdkGeometry
- ?
- gtk_window_set_geometry_hints(handle, Null, geom, GDK_HINT_MIN_SIZE)
- End Method
- Rem
- bbdoc: Sets the window icon with the specified pixmap.
- End Rem
- Method setIcon(pix:TPixmap)
- If pix <> Null Then
- Local pixmap:TPixmap = pix.convert( PF_RGBA8888 )
- Local icon:Byte Ptr = gdk_pixbuf_new_from_data(pixmap.pixels, GDK_COLORSPACE_RGB, True, 8, ..
- pixmap.width, pixmap.height, pixmap.Pitch, Null, Null)
- gtk_window_set_icon(handle, icon)
- End If
- End Method
-
- Rem
- bbdoc: Returns the window state.
- End Rem
- Method State:Int()
- Local flags:Int = Super.state()
-
- ' Note: you can be maximized and minimized at the same time, so that when
- ' we un-maximize (de-conify) it goes back to maximized.
- ' not sure if we should set them both in this instance. "Not" at the moment...
- If _minimized Then
- flags:| STATE_MINIMIZED
- Else If _maximized Then
- flags:| STATE_MAXIMIZED
- End If
-
- Return flags
- End Method
- Method SetText:Int(text:String)
- Local textPtr:Byte Ptr = text.ToUTF8String()
- gtk_window_set_title(handle, textPtr)
- MemFree(textPtr)
- End Method
-
- Method GetText:String()
- Return String.FromUTF8String(gtk_window_get_title(handle))
- End Method
- Method toString:String()
- Return "TGTKWindow"
- End Method
- End Type
- Rem
- bbdoc: A menu item.
- End Rem
- Type TGTKMenuItem Extends TGTKGadget
-
- Field popupMenu:Byte Ptr
- Field tag:Int = 0
- Field ignoreSelection:Int
- Field isCheckable:Int
- Field hasMnemonic:Int
- Field isSeparator:Int
- Field checked:Int
- Field text:String
- Field index:Int
- Field isStockItem:Int
-
- Global popupExtra:Object
- ' we use these to remember keycode and modifier just in case we need to make this
- ' menu item a check-type - in which case we delete and create a new one.
- Field myKeycode:Int
- Field myModifier:Int
-
- Field windowAccelGroup:Byte Ptr
-
- Field pixmap:TPixmap
- Field imagePixbuf:Byte Ptr
- Field image:Byte Ptr
-
- Function CreateMenuItem:TGTKMenuItem(label:String, tag:Int, parent:TGadget)
- Local this:TGTKMenuItem = New TGTKMenuItem
- this.initMenu(label, tag, parent)
- Return this
- End Function
- Method initMenu(_label:String, _tag:Int, _parent:TGadget)
- iclass = GTK_MENUITEM
- tag = _tag
-
- Local originalLabel:String = _label
- If TGTKWindow(_parent) Then
- windowAccelGroup = TGTKWindow(_parent).accelGroup
- Else If TGTKMenuItem(_parent)
- windowAccelGroup = TGTKMenuItem(_parent).windowAccelGroup
- Else
- 'Throw "menu item has no valid parent"
- ' A popupmenu... perhaps?
- windowAccelGroup = Null
- End If
- ' localisation
- If (LocalizationMode() & LOCALIZATION_OVERRIDE) Then
- MapInsert maxgui_driver._mapLocalized, Self, [_label,""]
- _label = LocalizeString(_label)
- End If
- setAccelMapId(_label)
- ' this is our menu item / text
- If _label = Null Or _label.length = 0 Then
- ' a separator
- handle = gtk_separator_menu_item_new()
- isSeparator = True
- Else
-
- ' convert underscores to doubles
- '_label = _label.replace("_", "__")
- ' a normal menu item
- ' Does it have a
- Local p:Int = _label.find("&")
- _label = processText(_label)
- Local _labelPtr:Byte Ptr = _label.ToUTF8String()
-
- ' does this label have a mnemonic?
- If p >= 0 Then
- '_label = _label.replace("&", "_")
- hasMnemonic = True
- handle = gtk_menu_item_new_with_mnemonic(_labelPtr)
- Else
- handle = gtk_menu_item_new_with_label(_labelPtr)
- End If
- MemFree(_labelPtr)
- End If
- text = _label
- ' let's hope that at least the parent is set!!
- If _parent Then
- parent = _parent
- If TGTKWindow(parent) Then
- Assert TGTKWindow(parent).menubar, "Cannot add menu to window created without WINDOW_MENU"
- ' add a new menu for the menubar
- ' Note : we never show this!! (on purpose)
- menu = gtk_menu_new()
- ' attach the menu text to the menu
- gtk_menu_item_set_submenu(handle, menu)
- ' add the menu to the menubar
- ' Need to make sure we have a menubar to add it to...
- ' In debug mode we'll have failed the above assertion already.
- If TGTKWindow(parent).menubar Then
- gtk_menu_shell_append(TGTKWindow(parent).menubar, handle)
- End If
- Else If TGTKMenuItem(parent) Then
- If TGTKMenuItem(parent).popupMenu Then
- gtk_container_add(TGTKMenuItem(parent).popupMenu, handle)
- Else
- ' we may need to create a sub menu to hold this!
- If Not TGTKMenuItem(parent).menu Then
- TGTKMenuItem(parent).menu = gtk_menu_new()
-
- ' attach the menu text to the menu
- gtk_menu_item_set_submenu(TGTKMenuItem(parent).handle, TGTKMenuItem(parent).menu)
-
- End If
-
- gtk_menu_shell_append(TGTKMenuItem(parent).menu, handle)
-
- End If
- ' we need to know our position in the menu
- index = parent.kids.count()
- End If
- gtk_widget_show(handle)
- ' Add an activate signal and store ourself in the menu data
- If Not TGTKWindow(parent) And Not isSeparator Then
- addConnection("activate", g_signal_cb2_ret(handle, "activate", MenuSelected, Self, Destroy, 0))
- g_object_set_data(handle, "_maxmenu", Self)
- End If
- Else ' popupmenu...
- popupMenu = gtk_menu_new()
- ' don't add OUR menu item to the list, as it is only a place holder.
- 'gtk_container_add(popupMenu, handle)
- gtk_widget_show(handle)
- End If
- End Method
- Method SetHotKey:Int(keycode:Int, modifier:Int)
- myKeycode = keycode
- myModifier = modifier
-
- setAccelEntry(keycode, modifier)
-
- ' override F10 menu access?
- If keycode = KEY_F10 And modifier = 0 Then
- Local settings:Byte Ptr = gtk_settings_get_default()
- gtk_settings_set_string_property(settings, "gtk-menu-bar-accel", "<alt>F10", AppFile)
- End If
- End Method
- Rem
- bbdoc: Callback function for selecting a menu option.
- about: Triggers a menu action event.<br/>
- NOTE - We have to ignore "obj" because it is not reliable
- End Rem
- Function MenuSelected:Int(widget:Byte Ptr, obj:Object)
- Local _menu:TGTKMenuItem = g_object_get_menudata(widget, "_maxmenu")
- Assert _menu, "Menu data is missing... !!!!"
- ' If this isn't a submenu root (one which has sub menus)
- ' then we can post the event
- If Not _menu.menu And Not _menu.ignoreSelection Then
- PostGuiEvent(EVENT_MENUACTION, _menu, _menu.tag,,,,_menu.popupextra)
- If _menu.popupExtra Then
- _menu.popupExtra = Null
- End If
- End If
- ' We need to keep the "checked" flag uptodate...
- If _menu.isCheckable Then
- _menu.checked = gtk_check_menu_item_get_active(widget)
- End If
-
- _menu.ignoreSelection = False
- Return True
- End Function
- Method SetSelected:Int(bool:Int)
- ' Don't do anything if we are already set...
- If (checked = bool) And isCheckable Then
- Return 0
- End If
- ignoreSelection = True
- ' if it's not checkable yet, we need to make it so
- If Not isCheckable And Not isSeparator And menu = Null Then
- ' remove the current menu
- If handle Then
- gtk_widget_destroy(handle)
- hasAccel = False
- End If
- Local textPtr:Byte Ptr = text.ToUtf8String()
- If hasMnemonic Then
- handle = gtk_check_menu_item_new_with_mnemonic(textPtr)
- Else
- handle = gtk_check_menu_item_new_with_label(textPtr)
- End If
- MemFree(textPtr)
- gtk_widget_show(handle)
- ' if we originally gave this a keycode / modifier, we need to re-establish it.
- If myKeycode <> 0 Then
- SetHotKey(myKeycode, myModifier)
- End If
- If TGTKWindow(parent) Then
- ' Only insert if menubar exists tho...
- If TGTKWindow(parent).menubar Then
- gtk_menu_shell_insert(TGTKWindow(parent).menubar, handle, index)
- End If
- Else If TGTKMenuItem(parent) Then
- If TGTKMenuItem(parent).menu Then
- gtk_menu_shell_insert(TGTKMenuItem(parent).menu, handle, index)
- End If
- EndIf
- ' we need to catch toggles!
- addConnection("toggled", g_signal_cb2_ret(handle, "toggled", MenuSelected, Self, Destroy, 0))
- g_object_set_data(handle, "_maxmenu", Self)
- isCheckable = True
- ' If we are not setting it checked it won't generate a toggle event...
- If Not bool Then
- ignoreSelection = False
- End If
- End If
- checked = bool
- gtk_check_menu_item_set_active(handle, checked)
- End Method
- Rem
- bbdoc: Returns menu state - checked or unchecked
- End Rem
- Method State:Int()
- Local _state:Int = Super.State()
-
- If isCheckable Then
- If gtk_check_menu_item_get_active(handle) Then
- _state :| STATE_SELECTED
- End If
- End If
- Return _state
- End Method
- Rem
- bbdoc: Returns the menu text
- End Rem
- Method GetText:String()
- If Not isSeparator Then
- Return String.FromUTF8String(gtk_label_get_text(gtk_bin_get_child(handle)))
- End If
- Return ""
- End Method
- Rem
- bbdoc: Sets the menu text
- End Rem
- Method SetText:Int(label:String)
- If Not isSeparator Then
- If label = Null Then
- label = ""
- End If
-
- text = processText(label)
- Local labelPtr:Byte Ptr = text.ToUTF8String()
- If label.find("&") >= 0 Then
- gtk_label_set_text_with_mnemonic(gtk_bin_get_child(handle), labelPtr)
- Else
- gtk_label_set_text(gtk_bin_get_child(handle), labelPtr)
- End If
- MemFree(labelPtr)
- End If
- End Method
-
- Method free:Int() Override
- Local _handle:Byte Ptr = handle
- Super.Free()
- If _handle
- gtk_widget_destroy(_handle)
- End If
- menu = Null
- If pixmap Then
- pixmap = Null
- End If
- If image Then
- ' g_object_unref(image) ' oops.. TODO: we might need this still.
- image = Null
- End If
- If imagePixbuf Then
- g_object_unref(imagePixbuf)
- imagePixbuf = Null
- End If
- End Method
- Method rethink:Int()
- End Method
- Method DoLayout:Int()
- End Method
- Method SetPixmap:Int(pix:TPixmap, flags:Int)
- If Not isSeparator Then
- If pix Then
- If PixmapFormat(pix) <> PF_RGBA8888 And PixmapFormat(pix) <> PF_BGRA8888 Then
- pixmap = pix.convert( PF_RGBA8888 )
- Else
- pixmap = pix
- End If
-
- If imagePixbuf Then
- g_object_unref(imagePixbuf)
- End If
-
- imagePixbuf = gdk_pixbuf_new_from_data(pixmap.pixels, GDK_COLORSPACE_RGB, True, 8, ..
- pixmap.width, pixmap.height, pixmap.Pitch, Null, Null)
-
- If Not image Then
- image = gtk_image_new()
- End If
- gtk_image_set_from_pixbuf(image, imagePixbuf)
- Else
- If pixmap Then
- gtk_image_clear(image)
- pixmap = Null
- End If
- End If
-
- If image Then
- ' TODO
- 'gtk_image_menu_item_set_image(handle, image)
- End If
- End If
- End Method
- Method toString:String()
- Return "TGTKMenuItem : " + text + " : " + Super.ToString()
- End Method
- Method SetEnabled:Int(bool:Int)
- gtk_widget_set_sensitive(handle, bool)
- End Method
- End Type
- Type TGTKIconStrip Extends TIconStrip
- Field images:Byte Ptr[]
- Field names:String[]
- Function IsNotBlank:Int(pixmap:TPixmap)
- Local w:Int = pixmap.width
- Local h:Int = pixmap.height
- Local c:Int = pixmap.ReadPixel(0,0)
- For Local x:Int = 0 Until h
- For Local y:Int = 0 Until h
- If pixmap.ReadPixel(x,y) <> c Then
- Return True
- End If
- Next
- Next
- End Function
-
- Function Create:TGTKIconStrip(source:Object)
-
- Local baseName:String = MilliSecs()
-
- Local pix:TPixmap = TPixmap(source)
- If Not pix Then
- pix = LoadPixmap(source)
- If Not pix Then
- Return Null
- End If
- End If
- Local n:Int = pix.width/pix.height
- If n = 0 Then
- Return Null
- End If
- Local pixmap:TPixmap = pix.convert( PF_RGBA8888 )
- Local icons:TGTKIconStrip = New TGTKIconStrip
- icons.pixmap=pixmap
- icons.count=n
- icons.images=New Byte Ptr[n]
- icons.names = New String[n]
- Local h:Int = pixmap.height
- Local w:Int = h
- For Local x:Int = 0 Until n
- Local winpix:TPixmap = pixmap.Window(x*w,0,w,pixmap.height)
- If IsNotBlank(winpix) Then
- icons.images[x]= gdk_pixbuf_new_from_data(winpix.pixels, GDK_COLORSPACE_RGB, True, 8, ..
- w, h, pixmap.Pitch, Null, Null)
- Local name:String = baseName + "_" + x
- icons.names[x] = name
- gtk_icon_theme_add_builtin_icon(name, h, icons.images[x])
- End If
- Next
- Return icons
- End Function
- End Type
- Rem
- bbdoc: Base type for button gadgets.
- End Rem
- Type TGTKButton Extends TGTKGadget
- Field hotkey:THotKey
- Field ignoreButtonClick:Int
- Method makeButton(label:String) Abstract
- Method initButton(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
-
- Init(iclass, x, y, w, h, style)
- parent = group
- ' localisation
- If (LocalizationMode() & LOCALIZATION_OVERRIDE) Then
- MapInsert maxgui_driver._mapLocalized, Self, [label,""]
- label = LocalizeString(label)
- End If
- makeButton(label)
- setAccelMapId(label)
- gtk_layout_put(TGTKContainer(parent).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- sensitivity:| SENSITIZE_MOUSE
-
- ' Set as default ?
- If style = BUTTON_OK Then
- gtk_widget_grab_default(handle)
- End If
- setShow(True)
- ' button clicked handler
- addConnection("clicked", g_signal_cb2(handle, "clicked", OnButtonClicked, Self, Destroy, 0))
- ' catch right-mouse buttons
- addConnection("button-press-event", g_signal_cb3_ret(handle, "button-press-event", OnMouseDown, Self, Destroy, 0))
- addConnection("enter-notify-event", g_signal_cb3_ret(handle, "enter-notify-event", OnMouseEnter, Self, Destroy, 0))
- addConnection("leave-notify-event", g_signal_cb3_ret(handle, "leave-notify-event", OnMouseLeave, Self, Destroy, 0))
- End Method
- Rem
- bbdoc: Callback for button click.
- End Rem
- Function OnButtonClicked(widget:Byte Ptr, obj:Object)
- If Not TGTKButton(obj).ignoreButtonClick Then
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), ButtonState(TGadget(obj)))
- End If
-
- TGTKButton(obj).ignoreButtonClick = False
- End Function
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then ' right mouse button
- PostGuiEvent(EVENT_GADGETMENU, TGadget(obj),,,Int(x),Int(y))
- Return True
- End If
- Return False
- End Function
- Function OnMouseEnter:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
-
- If TGTKGadget(obj).visible Then
- PostGuiEvent(EVENT_MOUSEENTER, TGadget(obj))
- End If
- Return False
- End Function
- Function OnMouseLeave:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKGadget(obj).visible Then
- PostGuiEvent(EVENT_MOUSELEAVE, TGadget(obj))
- End If
- Return False
- End Function
- Rem
- bbdoc: Sets the button text.
- End Rem
- Method SetText:Int(text:String)
- text = processText(text)
- Local textPtr:Byte Ptr = text.ToUTF8String()
- gtk_button_set_label(handle, textPtr)
- MemFree(textPtr)
- gtk_button_set_use_underline(handle, True)
- End Method
- Rem
- bbdoc: Returns the button text.
- End Rem
- Method GetText:String()
- Return String.FromUTF8String(gtk_button_get_label(handle))
- End Method
- Rem
- bbdoc: Sets the button text color.
- End Rem
- Method SetTextColor:Int(r:Int, g:Int, b:Int)
- Local color:GdkRGBA = New GdkRGBA(r / 255.0, g / 255.0, b / 255.0)
-
- Local buttonLabel:Byte Ptr = gtk_bin_get_child(handle)
- gtk_widget_override_color(buttonLabel, GTK_STATE_FLAG_NORMAL, color)
- gtk_widget_override_color(buttonLabel, GTK_STATE_FLAG_ACTIVE, color)
- gtk_widget_override_color(buttonLabel, GTK_STATE_FLAG_PRELIGHT, color)
- End Method
- Method free:Int() Override
- Super.Free()
- If handle
- gtk_widget_destroy(handle)
- EndIf
- handle = Null
- End Method
- Rem
- bbdoc: Sets a hot key for the button.
- End Rem
- Method SetHotKey:Int(keycode:Int, modifier:Int)
- setAccelEntry(keycode, modifier)
- End Method
- Method toString:String()
- Return "TGTKButton"
- End Method
- End Type
- Rem
- bbdoc: A push button
- End Rem
- Type TGTKButtonPush Extends TGTKButton
- Function CreateButton:TGTKButtonPush(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKButtonPush = New TGTKButtonPush
- this.initButton(x, y, w, h, label, group, style)
- Return this
- End Function
- Method makeButton(label:String)
- label = processText(label)
-
- Local labelPtr:Byte Ptr = label.ToUTF8String()
- handle = gtk_button_new_with_label(labelPtr)
- MemFree(labelPtr)
- gtk_button_set_use_underline(handle, True)
- ' enable "default" gadget functionality
- g_object_set_int(handle, "can-default", True)
- End Method
- Method SetText:Int(text:String)
- text = processText(text)
- Local textPtr:Byte Ptr = text.ToUTF8String()
- gtk_button_set_label(handle, textPtr)
- MemFree(textPtr)
- gtk_button_set_use_underline(handle, True)
- End Method
- Method SetPixmap:Int(pix:TPixmap, flags:Int = 0)
- If pix Then
- Local pixmap:TPixmap
- If pix.format <> PF_RGBA8888 Then
- pixmap = pix.convert( PF_RGBA8888 )
- Else
- pixmap = pix
- End If
-
- Local image:Byte Ptr = gtk_image_new_from_pixbuf(gdk_pixbuf_new_from_data(pixmap.pixels, GDK_COLORSPACE_RGB, True, 8, ..
- pixmap.width, pixmap.height, pixmap.Pitch, Null, Null))
- If image Then
- gtk_button_set_image(handle, image)
- gtk_button_set_image_position(handle, GTK_POS_LEFT)
- End If
- End If
- End Method
- Method toString:String()
- Return "TGTKButtonPush"
- End Method
- End Type
- Rem
- bbdoc: A button which has a toggle-type usage (radio / checkbox)
- End Rem
- Type TGTKToggleButton Extends TGTKButton
- Field isSelected:Int
- Method SetSelected:Int(bool:Int)
- If bool <> gtk_toggle_button_get_active(handle) Then
- ignoreButtonClick = True
- End If
-
- gtk_toggle_button_set_active(handle, bool)
-
- isSelected = bool
- End Method
- Method State:Int()
- Local flags:Int = Super.State()
- If gtk_toggle_button_get_active(handle) Then
- flags:|STATE_SELECTED
- End If
- Return flags
- End Method
- Rem
- bbdoc: Callback for button click.
- End Rem
- Function OnButtonClicked(widget:Byte Ptr, obj:Object)
- If Not TGTKButton(obj).ignoreButtonClick Then
- If TGTKToggleButton(obj).isSelected <> gtk_toggle_button_get_active(widget)
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), ButtonState(TGadget(obj)))
- End If
- TGTKToggleButton(obj).isSelected = gtk_toggle_button_get_active(widget)
- End If
-
- TGTKButton(obj).ignoreButtonClick = False
- End Function
- Method disableEvents()
- End Method
-
- Method enableEvents()
- End Method
-
- End Type
- Rem
- bbdoc: A radio button.
- End Rem
- Type TGTKButtonRadio Extends TGTKToggleButton
- Function CreateButton:TGTKButtonRadio(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKButtonRadio = New TGTKButtonRadio
- this.initButton(x, y, w, h, label, group, style)
- Return this
- End Function
- Method makeButton(label:String)
- Local _group:Byte Ptr = TGTKContainer(parent).radioGroup
- label = processText(label)
- Local labelPtr:Byte Ptr = label.ToUTF8String()
- If _group = Null Then
- handle = gtk_radio_button_new_with_label(Null, labelPtr)
- gtk_toggle_button_set_active(handle, True)
- isSelected = True
- Else
- handle = gtk_radio_button_new_with_label(_group, labelPtr)
- End If
- MemFree(labelPtr)
-
- ' update the radiogroup, ready for a new radio button...
- TGTKContainer(parent).radioGroup = gtk_radio_button_get_group(handle)
-
- gtk_button_set_use_underline(handle, True)
-
- If style & BUTTON_PUSH Then
- gtk_toggle_button_set_mode(handle, False)
- End If
-
- End Method
- Method SetSelected:Int(bool:Int)
- disableEvents()
-
- gtk_toggle_button_set_active(handle, bool)
-
- enableEvents()
-
- isSelected = bool
- End Method
- Function OnButtonClicked(widget:Byte Ptr, obj:Object)
- TGTKToggleButton(obj).isSelected = gtk_toggle_button_get_active(widget)
- If TGTKToggleButton(obj).isSelected Then
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), ButtonState(TGadget(obj)))
- End If
-
- TGTKButton(obj).ignoreButtonClick = False
- End Function
- Method disableEvents()
- For Local gadget:TGTKButtonRadio = EachIn parent.kids
- Local id:TGTKInteger = TGTKInteger(gadget.connectionMap.ValueForKey("clicked"))
- If id Then
- g_signal_handler_disconnect(gadget.handle, id.value)
- End If
- Next
- End Method
-
- Method enableEvents()
- For Local gadget:TGTKButtonRadio = EachIn parent.kids
- gadget.addConnection("clicked", g_signal_cb2(gadget.handle, "clicked", OnButtonClicked, gadget, Destroy, 0))
- Next
- End Method
- Method toString:String()
- Return "TGTKButtonRadio"
- End Method
- End Type
- Rem
- bbdoc: A checkbox button
- End Rem
- Type TGTKButtonCheckbox Extends TGTKToggleButton
- Function CreateButton:TGTKButtonCheckbox(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKButtonCheckbox = New TGTKButtonCheckbox
- this.initButton(x, y, w, h, label, group, style)
- Return this
- End Function
- Method makeButton(label:String)
- label = processText(label)
-
- Local labelPtr:Byte Ptr = label.ToUTF8String()
- handle = gtk_check_button_new_with_label(labelPtr)
- MemFree(labelPtr)
-
- gtk_button_set_use_underline(handle, True)
- If style & BUTTON_PUSH Then
- gtk_toggle_button_set_mode(handle, False)
- End If
- End Method
- Method toString:String()
- Return "TGTKButtonCheckbox"
- End Method
- End Type
- Rem
- bbdoc: A label.
- End Rem
- Type TGTKLabel Extends TGTKGadget
- ' surrounding frame widget, if any
- Field frame:Byte Ptr
- Field hasFrame:Int
- Field isSeparator:Int
- Field ebox:Byte Ptr
- Function CreateLabel:TGTKLabel(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKLabel = New TGTKLabel
- this.initLabel(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initLabel(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Init(GTK_LABEL, x, y, w, h, style)
- If style & LABEL_FRAME And style & LABEL_SUNKENFRAME Then
- isSeparator = True
- End If
- If Not isSeparator Then
- Local labelPtr:Byte Ptr = label.ToUTF8String()
- handle = gtk_label_new(labelPtr)
- MemFree(labelPtr)
- If style & LABEL_RIGHT Then
- gtk_misc_set_alignment(handle, 1, 0.5)
- Else If style & LABEL_CENTER Then
- gtk_misc_set_alignment(handle, 0.5, 0.5)
- Else
- gtk_misc_set_alignment(handle, 0, 0.5)
- End If
- sensitivity:| SENSITIZE_MOUSE
-
- ' since a Label can't accept events, we wrap it inside an event box which can
- ebox = gtk_event_box_new()
- gtk_event_box_set_visible_window(ebox, False)
- gtk_widget_add_events(ebox, GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK)
-
- addConnection("enter-notify-event", g_signal_cb3_ret(ebox, "enter-notify-event", OnMouseEnter, Self, Destroy, 0))
- addConnection("leave-notify-event", g_signal_cb3_ret(ebox, "leave-notify-event", OnMouseLeave, Self, Destroy, 0))
- addConnection("button-press-event", g_signal_cb3_ret(ebox, "button-press-event", OnMouseDown, Self, Destroy, 0))
- ' show the box
- gtk_widget_show(ebox)
- ' add the label to the eventbox
- gtk_container_add(ebox, handle)
-
- If (LocalizationMode() & LOCALIZATION_OVERRIDE) Then
- LocalizeGadget(Self, label)
- Else
- SetText(label)
- EndIf
- End If
- ' Should we add a frame?
- If style & LABEL_FRAME Or style & LABEL_SUNKENFRAME Then
- hasFrame = True
- If isSeparator Then
- If w < h Then
- frame = gtk_separator_new(GTK_ORIENTATION_VERTICAL)
- Else
- frame = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL)
- End If
- handle = frame
- Else
- frame = gtk_frame_new(Null)
- If style & LABEL_FRAME Then
- gtk_frame_set_shadow_type(frame, GTK_SHADOW_ETCHED_IN)
- Else
- gtk_frame_set_shadow_type(frame, GTK_SHADOW_IN)
- End If
- gtk_container_add(frame, ebox)
- End If
- gtk_layout_put(TGTKContainer(group).container, frame, x, y)
- gtk_widget_set_size_request(frame, w, Max(h,0))
- Else
- gtk_layout_put(TGTKContainer(group).container, ebox, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- End If
- setShow(True)
- End Method
- Rem
- bbdoc: Show or Hide the label
- End Rem
- Method SetShow:Int(truefalse:Int)
- visible = truefalse
- mySetVisible = visible
-
- If hasFrame Then
- If truefalse Then
- gtk_widget_show(frame)
- Else
- gtk_widget_hide(frame)
- EndIf
- End If
- If Not isSeparator Then
- If truefalse Then
- gtk_widget_show(handle)
- gtk_widget_show(ebox)
- Else
- gtk_widget_hide(ebox)
- EndIf
- End If
- End Method
- Method SetText:Int(text:String)
- If Not isSeparator Then
- Local textPtr:Byte Ptr = text.ToUtf8String()
- gtk_label_set_text(handle, textPtr)
- MemFree(textPtr)
- End If
- End Method
-
- Method GetText:String()
- If Not isSeparator Then
- Return String.FromUTF8String(gtk_label_get_text(handle))
- End If
- Return Null
- End Method
- Method free:Int() Override
- Super.Free()
- If frame
- gtk_widget_destroy(frame)
- Else
- If ebox Then
- gtk_widget_destroy(ebox)
- End If
- EndIf
- handle = Null
- frame = Null
- ebox = Null
- End Method
- Method setToolTip:Int(tip:String)
-
- If Not isSeparator Then
- If tip And tip.length > 0 Then
- Local tipPtr:Byte Ptr = tip.ToUTF8String()
- gtk_widget_set_tooltip_text(ebox, tipPtr)
- MemFree(tipPtr)
- Else
- gtk_widget_set_has_tooltip(ebox, False)
- End If
- Else
- If tip And tip.length > 0 Then
- Local tipPtr:Byte Ptr = tip.ToUTF8String()
- gtk_widget_set_tooltip_text(handle, tipPtr)
- MemFree(tipPtr)
- Else
- gtk_widget_set_has_tooltip(handle, False)
- End If
- End If
- End Method
- Method Rethink:Int()
- If frame Then
- gtk_layout_move(TGTKContainer(parent).container, frame, Max(xpos, 0), Max(ypos, 0))
- gtk_widget_set_size_request(frame, Max(width,0), Max(height,0))
- Else If handle Then
- gtk_layout_move(TGTKContainer(parent).container, ebox, Max(xpos, 0), Max(ypos, 0))
- gtk_widget_set_size_request(handle, Max(width,0), Max(height,0))
- End If
- End Method
- Function OnMouseEnter:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
-
- If TGTKGadget(obj).visible Then
- PostGuiEvent(EVENT_MOUSEENTER, TGadget(obj))
- End If
-
- Return False
- End Function
- Function OnMouseLeave:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKGadget(obj).visible Then
- PostGuiEvent(EVENT_MOUSELEAVE, TGadget(obj))
- End If
-
- Return False
- End Function
- Rem
- bbdoc: Callback For mouse button press.
- End Rem
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
-
- If button = 3 Then ' right mouse button
- PostGuiEvent(EVENT_GADGETMENU, TGadget(obj),,,Int(x),Int(y))
- Else ' other mouse buttons
- If button = 2 Then
- button = 3
- End If
- PostGuiEvent(EVENT_MOUSEDOWN, TGadget(obj),button,,Int(x),Int(y))
- End If
-
- Return True
- End Function
- Rem
- bbdoc: Sets the label text color.
- End Rem
- Method SetTextColor:Int(r:Int, g:Int, b:Int)
- Local color:GdkRGBA = New GdkRGBA(r / 255.0, g / 255.0, b / 255.0)
- gtk_widget_override_color(handle, GTK_STATE_FLAG_NORMAL, color)
- End Method
- Method toString:String()
- Return "TGTKLabel"
- End Method
- End Type
- Rem
- bbdoc: Base type for editable gadgets (textfield / textarea).
- End Rem
- Type TGTKEditable Extends TGTKGadget
- Field ignoreTextChange:Int
- Method Activate:Int(cmd:Int)
- Super.Activate(cmd)
- End Method
- Function OnTextChanged(widget:Byte Ptr, obj:Object)
- If Not TGTKEditable(obj).ignoreTextChange Then
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj))
- End If
-
- If TGTKEditable(obj).ignoreTextChange Then
- TGTKEditable(obj).ignoreTextChange:-1
- End If
- End Function
- ' key handler stuff - filtering etc
- Function OnKeyDown:Int(widget:Byte Ptr, gdkEvent:Byte Ptr, obj:Object)
- Local source:TGTKEditable = TGTKEditable(obj)
- ' only if we are using a filter...
- If source And source.eventfilter <> Null Then
- Local _key:Int, _mods:Int
- bmx_gtk3maxgui_gdkeventkey(gdkEvent, Varptr _key, Varptr _mods)
- Local key:Int = TGTKKeyMap.mapBack(_key)
- Local mods:Int = TGTKKeyMap.mapModifierBack(_mods)
-
- Local event:TEvent=HotKeyEvent( key,mods, Null )
- If event Then
- event.emit()
- Return True
- EndIf
- event = CreateEvent(EVENT_KEYDOWN, source, key, mods)
-
- If Not source.eventfilter(event, source.context) Then
- Return True
- End If
- Local char:Int = gdk_keyval_to_unicode(_key)
- ' we sometimes get 0 from this function when key is valid... so set it to key just so that it has a value.
- If char = 0 And key <> 0 Then
- char = key
- End If
- event = CreateEvent(EVENT_KEYCHAR, source, char, mods)
- If Not source.eventfilter(event, source.context) Then
- Return True
- End If
- EndIf
- Return False
- End Function
- End Type
- Rem
- bbdoc: A Text field.
- End Rem
- Type TGTKTextField Extends TGTKEditable
- Field isPassword:Int
-
- Function CreateTextField:TGTKTextField(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKTextField = New TGTKTextField
- this.initTextField(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initTextField(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- handle = gtk_entry_new()
- Init(GTK_TEXTFIELD, x, y, w, h, style)
- If style Then
- isPassword = True
- gtk_entry_set_visibility(handle, False)
- End If
- ' causes the default gadget to be activated when Enter is pressed inside this Text Field.
- g_object_set_int(handle, "activates-default", True)
- setShow(True)
- gtk_layout_put(TGTKContainer(group).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- ' add callbacks
- addConnection("changed", g_signal_cb2(handle, "changed", OnTextChanged, Self, Destroy, 0))
- addConnection("key-press-event", g_signal_cb3_ret(handle, "key-press-event", OnKeyDown, Self, Destroy, 0))
- addConnection("focus-out-event", g_signal_cb3_ret(handle, "focus-out-event", OnFocusLost, Self, Destroy, 0))
- ' catch right-mouse buttons
- addConnection("button-press-event", g_signal_cb3_ret(handle, "button-press-event", OnMouseDown, Self, Destroy, 0))
- End Method
- Rem
- bbdoc: Returns the textfield text.
- End Rem
- Method GetText:String()
- Return String.FromUTF8String(gtk_entry_get_text(handle))
- End Method
- Rem
- bbdoc: Sets the textfield text.
- End Rem
- Method SetText:Int(txt:String)
- If txt = Null
- txt = ""
- End If
-
- ' when set to blank, it raises 2 change events?
- If txt = "" And GetText() <> "" Then
- ignoreTextChange:+1
- End If
-
- If txt <> GetText() Then
- ignoreTextChange:+1
- End If
-
- Local txtPtr:Byte Ptr = txt.ToUTF8String()
- gtk_entry_set_text(handle, txtPtr)
- MemFree(txtPtr)
- End Method
- Method free:Int() Override
- Super.Free()
- If handle
- gtk_widget_destroy(handle)
- EndIf
- handle = Null
- End Method
- Method Activate:Int(cmd:Int)
- Super.Activate(cmd)
- Select cmd
- Case ACTIVATE_CUT
- gtk_editable_cut_clipboard(handle)
- Case ACTIVATE_COPY
- gtk_editable_copy_clipboard(handle)
- Case ACTIVATE_PASTE
- gtk_editable_paste_clipboard(handle)
- End Select
- End Method
-
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then ' right mouse button
- PostGuiEvent(EVENT_GADGETMENU, TGadget(obj),,,Int(x),Int(y))
- Return True
- End If
- Return False
- End Function
- Method toString:String()
- Return "TGTKTextField"
- End Method
- End Type
- Rem
- bbdoc: A base for list gadgets.
- End Rem
- Type TGTKList Extends TGTKGadget
- Field icons:TGTKIconStrip
- Field _store:Byte Ptr
- Field _selection:Byte Ptr
- ' sometimes we need to ignore events because we made them ourselves - rather than the user selecting
- ' something.
- Field ignoreListChangeEvent:Int
- Method SetIconStrip:Int(iconstrip:TIconStrip)
- icons = TGTKIconStrip(iconstrip)
- End Method
- Method populateListRow(index:Int, text:String, tip:String, icon:Int, iter:Byte Ptr)
- ' need to put the string in a GValue for placing into the list
- Local _value:Byte Ptr = bmx_gtk3_gvalue_new(G_TYPE_STRING)
- 'g_value_init(_value, G_TYPE_STRING)
- Local textPtr:Byte Ptr = text.ToUTF8String()
- g_value_set_string(_value, textPtr)
- MemFree(textPtr)
-
- ' set the row value
- If TGTKListbox(Self) Or TGTKComboBox(Self) Then
- gtk_list_store_set_value(_store, iter, 1, _value)
- Else
- gtk_tree_store_set_value(_store, iter, 1, _value)
- End If
-
- ' tidy up !
- g_value_unset(_value)
- Local image:Byte Ptr
- If icons And icon>=0 Then
- image = icons.images[icon]
- End If
- If image Then
- ' Insert the appropriate icon
- g_value_init(_value, gdk_pixbuf_get_type())
- g_value_set_object(_value, image)
-
- ' set the row value
- If TGTKListbox(Self) Or TGTKComboBox(Self) Then
- gtk_list_store_set_value(_store, iter, 0, _value)
- Else
- gtk_tree_store_set_value(_store, iter, 0, _value)
- End If
-
- ' tidy up !
- g_value_unset(_value)
- Else
- ' clear out an icon if one is present in this entry
- g_value_init(_value, gdk_pixbuf_get_type())
- g_value_set_object(_value, Null)
-
- ' set the row value
- If TGTKListbox(Self) Or TGTKComboBox(Self) Then
- gtk_list_store_set_value(_store, iter, 0, _value)
- Else
- gtk_tree_store_set_value(_store, iter, 0, _value)
- End If
-
- ' tidy up !
- g_value_unset(_value)
- End If
- bmx_gtk3_gvalue_free(_value)
-
- End Method
- Method initColumns()
- ' add a column to the list :
- Local col:Byte Ptr = gtk_tree_view_column_new()
- ' pack column into list
- gtk_tree_view_append_column(handle, col)
- Local pixRenderer:Byte Ptr = gtk_cell_renderer_pixbuf_new()
- Local textRenderer:Byte Ptr = gtk_cell_renderer_text_new()
- ' pack cell renderers into column
- gtk_tree_view_column_pack_start(col, pixRenderer, False)
- gtk_tree_view_column_pack_end(col, textRenderer, True)
- gtk_tree_view_column_add_attribute(col, pixRenderer, "pixbuf", 0)
- gtk_tree_view_column_add_attribute(col, textRenderer, "text", 1)
- End Method
- Function OnSelectionChanged(_sel:Byte Ptr, obj:Object) Abstract
- End Type
- Rem
- bbdoc: A combo box
- End Rem
- Type TGTKComboBox Extends TGTKList
- Field isEditable:Int
- Function CreateComboBox:TGTKComboBox(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKComboBox = New TGTKComboBox
- this.initComboBox(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initComboBox(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- If style = COMBOBOX_EDITABLE Then
- isEditable = True
- handle = gtk_combo_box_new_with_entry()
- Else
- handle = gtk_combo_box_new()
- End If
- Init(GTK_COMBOBOX, x, y, w, h, style)
-
- ' Create a list store of pixbuf and string (the two displayable columns)
- _store = gtk_list_store_new(2, gdk_pixbuf_get_type(), G_TYPE_STRING)
- gtk_combo_box_set_model(handle, _store)
-
- ' for editable, we need to tell it which column contains the text part
- If isEditable Then
- gtk_combo_box_set_entry_text_column(handle, 1)
- End If
- initColumns()
- setShow(True)
- gtk_layout_put(TGTKContainer(group).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
-
- addConnection("changed", g_signal_cb2(handle, "changed", OnSelectionChanged, Self, Destroy, 0))
- ' catch right-mouse buttons
- addConnection("button-press-event", g_signal_cb3_ret(handle, "button-press-event", OnMouseDown, Self, Destroy, 0))
- End Method
-
- Method initColumns()
- gtk_cell_layout_clear(handle)
- Local pixRenderer:Byte Ptr = gtk_cell_renderer_pixbuf_new()
- Local textRenderer:Byte Ptr = gtk_cell_renderer_text_new()
- ' pack cell renderers into layout
- gtk_cell_layout_pack_start(handle, pixRenderer, False)
- gtk_cell_layout_pack_end(handle, textRenderer, True)
- gtk_cell_layout_add_attribute(handle, pixRenderer, "pixbuf", 0)
- gtk_cell_layout_add_attribute(handle, textRenderer, "text", 1)
- End Method
- Rem
- bbdoc: Callback for selection change.
- End Rem
- Function OnSelectionChanged(widget:Byte Ptr, obj:Object)
- Local row:Int = TGTKComboBox(obj).SelectedItem()
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), row,,,,TGadget(obj).ItemExtra(row))
- End Function
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then ' right mouse button
- Local treePath:Byte Ptr
- Local row:Int = TGTKComboBox(obj).SelectedItem()
-
- If row >= 0 Then
- PostGuiEvent(EVENT_GADGETMENU, TGadget(obj),row,,Int(x),Int(y),TGTKList(obj).items[row].extra)
- Else
- PostGuiEvent(EVENT_GADGETMENU, TGadget(obj),row,,Int(x),Int(y))
- End If
- Return True
- End If
- Return False
- End Function
-
- Method InsertListItem:Int(index:Int, text:String, tip:String, icon:Int, tag:Object)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- gtk_list_store_insert(_store, iter, index)
- populateListRow(index, text, tip, icon, iter)
- bmx_gtk3_gtktreeiter_free(iter)
- End Method
- Method SetListItem:Int(index:Int, text:String, tip:String, icon:Int, tag:Object)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local found:Int = gtk_tree_model_iter_nth_child(_store, iter, Null, index)
- If found Then
- populateListRow(index, text, tip, icon, iter)
- End If
- bmx_gtk3_gtktreeiter_free(iter)
- End Method
- Method SelectedItem:Int()
- Return gtk_combo_box_get_active(handle)
- End Method
- Method SetListItemState:Int(index:Int ,state:Int)
- If state & STATE_SELECTED Then
- gtk_combo_box_set_active(handle, index)
- End If
- End Method
- Method ClearListItems:Int()
- gtk_list_store_clear(_store)
- End Method
- Method RemoveListItem:Int(index:Int)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local found:Int = gtk_tree_model_iter_nth_child(_store, iter, Null, index)
-
- If found Then
- gtk_list_store_remove(_store, iter)
- End If
- bmx_gtk3_gtktreeiter_free(iter)
- End Method
- Method ItemText:String(index:Int)
- If index < 0 Or index >= items.length Then
- Return GetText()
- End If
- Return items[index].text
- End Method
- Method GetText:String()
- Local st:String
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local found:Int = gtk_combo_box_get_active_iter(handle, iter)
-
- If found Then
- Local _value:Byte Ptr = bmx_gtk3_gvalue_new(G_TYPE_STRING)
-
- gtk_tree_model_get_value(_store, iter, 0, _value)
-
- st = String.FromUTF8String(g_value_get_string(_value))
-
- ' tidy up !
- g_value_unset(_value)
- bmx_gtk3_gvalue_free(_value)
- End If
-
- Return st
- End Method
- Method free:Int() Override
- Super.Free()
- If handle
- gtk_widget_destroy(handle)
- EndIf
- handle = Null
- End Method
- Method toString:String()
- Return "TGTKComboBox"
- End Method
- End Type
- Rem
- bbdoc: A scrollable list.
- End Rem
- Type TGTKListWithScrollWindow Extends TGTKList
- Field scrollWindow:Byte Ptr
- Method Init(GadgetClass:Int, x:Int, y:Int, w:Int, h:Int, style:Int)
- Super.init(iclass, x, y, w, h, style)
-
- handle = gtk_tree_view_new()
- gtk_tree_view_set_headers_visible(handle, False)
- ' a reference to the selection object
- _selection = gtk_tree_view_get_selection(handle)
- ' currently we only support SINGLE row selection
- gtk_tree_selection_set_mode(_selection, GTK_SELECTION_SINGLE)
- scrollWindow = gtk_scrolled_window_new(Null, Null)
- ' set container resize mode
- gtk_container_set_resize_mode(scrollWindow, GTK_RESIZE_QUEUE)
- ' set scrollbar policy
- gtk_scrolled_window_set_policy(scrollWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC)
- ' show
- gtk_widget_show(scrollWindow)
- ' add the html view to the scroll view
- gtk_container_add(scrollWindow, handle)
- ' add callback
- addConnection("changed", g_signal_cb2(_selection, "changed", OnSelectionChanged, Self, Destroy, 0))
-
- ' catch right-mouse buttons
- addConnection("button-press-event", g_signal_cb3_ret(handle, "button-press-event", OnMouseDown, Self, Destroy, 0))
- End Method
- Method SetShow:Int(truefalse:Int)
- visible = truefalse
- mySetVisible = visible
-
- If truefalse Then
- gtk_widget_show(scrollWindow)
- gtk_widget_show(handle)
- Else
- gtk_widget_hide(scrollWindow)
- gtk_widget_hide(handle)
- EndIf
- UpdateChildVisibility()
- End Method
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- End Function
- End Type
- Rem
- bbdoc: List box
- End Rem
- Type TGTKListbox Extends TGTKListWithScrollWindow
- Field currentSelection:Int = -1
- Function CreateListBox:TGTKListbox(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKListbox = New TGTKListbox
- this.initListBox(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initListBox(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Init(GTK_LISTBOX, x, y, w, h, style)
- ' had intended using GTK_TYPE_PIXBUF here but it's a different value every time!?!
- _store = gtk_list_store_new(2, gdk_pixbuf_get_type(), G_TYPE_STRING)
- initColumns()
- gtk_tree_view_set_model(handle, _store)
- ' remove *our* reference to the store... when the list is destroyed this will be too
- g_object_unref(_store)
- addConnection("row-activated", g_signal_cb4(handle, "row-activated", OnRowActivated, Self, Destroy, 0))
- SetShow(True)
- gtk_layout_put(TGTKContainer(group).container, scrollwindow, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- End Method
- Method InsertListItem:Int(index:Int, text:String, tip:String, icon:Int, extra:Object)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- gtk_list_store_insert(_store, iter, index)
- populateListRow(index, text, tip, icon, iter)
- bmx_gtk3_gtktreeiter_free(iter)
- End Method
- Method SetListItem:Int(index:Int, text:String, tip:String, icon:Int, tag:Object)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local found:Int = gtk_tree_model_iter_nth_child(_store, iter, Null, index)
- If found Then
- populateListRow(index, text, tip, icon, iter)
- End If
- bmx_gtk3_gtktreeiter_free(iter)
- End Method
- Rem
- bbdoc: Removes an item from the list at the given index
- End Rem
- Method RemoveListItem:Int(index:Int)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local found:Int = gtk_tree_model_iter_nth_child(_store, iter, Null, index)
-
- If found Then
- If gtk_tree_selection_iter_is_selected(_selection, iter) Then
- ignoreListChangeEvent = True
- End If
- gtk_list_store_remove(_store, iter)
- End If
- bmx_gtk3_gtktreeiter_free(iter)
- End Method
- Method SetListItemState:Int(index:Int, state:Int)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local found:Int = gtk_tree_model_iter_nth_child(_store, iter, Null, index)
- If found Then
- If state & STATE_SELECTED Then
- ignoreListChangeEvent = True
- gtk_tree_selection_select_iter(_selection, iter)
- Else
- If gtk_tree_selection_iter_is_selected(_selection, iter) Then
- ignoreListChangeEvent = True
- End If
-
- gtk_tree_selection_unselect_iter(_selection, iter)
- End If
- End If
- bmx_gtk3_gtktreeiter_free(iter)
- End Method
- Method ListItemState:Int(index:Int)
- Local state:Int = 0
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local found:Int = gtk_tree_model_iter_nth_child(_store, iter, Null, index)
- If found Then
- If gtk_tree_selection_iter_is_selected(_selection, iter) Then
- state:| STATE_SELECTED
- End If
- End If
- bmx_gtk3_gtktreeiter_free(iter)
- Return state
- End Method
- Function OnSelectionChanged(_sel:Byte Ptr, obj:Object)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local row:Int = -1
- Local selected:Int = gtk_tree_selection_get_selected(_sel, Null, iter)
- If selected Then
- Local path:Byte Ptr = gtk_tree_model_get_string_from_iter(TGTKList(obj)._store, iter)
- row = String.fromCString(path).toInt()
- g_free(path)
- End If
- If TGTKListbox(obj).currentSelection <> row Then
-
- TGTKListbox(obj).currentSelection = row
-
- If Not TGTKList(obj).ignoreListChangeEvent Then
- PostGuiEvent(EVENT_GADGETSELECT, TGadget(obj), row,,,,TGadget(obj).ItemExtra(row))
- End If
- End If
- TGTKList(obj).ignoreListChangeEvent = False
-
- bmx_gtk3_gtktreeiter_free(iter)
- End Function
- Rem
- bbdoc: Callback for listbox activation (double-click).
- End Rem
- Function OnRowActivated(widget:Byte Ptr, treePath:Byte Ptr, treeviewColumn:Byte Ptr, obj:Object)
- Local p:Byte Ptr = gtk_tree_path_to_string(treePath)
- Local row:Int
-
- If p <> Null Then
- row = String.fromCString(p).toInt()
- End If
- ' clean up mem
- g_free(p)
- If row >= 0 Then
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj),row ,,,,TGTKList(obj).items[row].extra)
- Else
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), row)
- End If
- End Function
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then ' right mouse button
- Local treePath:Byte Ptr
- Local row:Int = -1
-
- ' Get tree path For row that was clicked
- If gtk_tree_view_get_path_at_pos(widget, Int(x), Int(y), Varptr treePath, Null, Null, Null) Then
- Local p:Byte Ptr = gtk_tree_path_to_string(treePath)
-
- If p <> Null Then
- row = String.fromCString(p).toInt()
- End If
- ' clean up mem
- g_free(p)
- gtk_tree_path_free(treePath)
- End If
-
- If row >= 0 Then
- PostGuiEvent(EVENT_GADGETMENU, TGadget(obj),row,,Int(x),Int(y),TGTKList(obj).items[row].extra)
- Else
- PostGuiEvent(EVENT_GADGETMENU, TGadget(obj),row,,Int(x),Int(y))
- End If
- Return True
- End If
- Return False
- End Function
-
- Method ClearListItems:Int()
- If gtk_tree_selection_get_selected(_selection, Null, Null) Then
- ignoreListChangeEvent = True
- End If
- gtk_list_store_clear(_store)
- End Method
- Method rethink:Int()
- If handle Then
- gtk_layout_move(TGTKContainer(parent).container, scrollwindow, Max(xpos, 0), Max(ypos, 0))
- gtk_widget_set_size_request(scrollwindow, Max(width,0), Max(height,0))
- End If
- End Method
- Method free:Int() Override
- Super.free()
- ' destroying the widget should destroy the handle (list) too.
- If scrollWindow Then
- gtk_widget_destroy(scrollWindow)
- End If
-
- scrollWindow = Null
- handle = Null
- End Method
- Method toString:String()
- Return "TGTKListbox"
- End Method
- End Type
- Rem
- bbdoc: A node in the tree view.
- End Rem
- Type TGTKTreeViewNode Extends TGTKListWithScrollWindow
- ' is this node the root node?
- Field isRoot:Int
- ' internal representation of node position in the tree
- Field _path:String
- ' direct access to the node in the tree
- Field myIter:Byte Ptr
- ' icon to display for this node
- Field _icon:Int
- ' flag to prevent non-user events from firing
- Field ignoreExpand:Int
- Field ignoreCollapse:Int
- ' text of this node
- Field _text:String
- Function _createNode:TGTKTreeViewNode(parent:TGTKTreeViewNode, index:Int)
- Local this:TGTKTreeViewNode = New TGTKTreeViewNode
- this.kids = New TEList
- this.handle = parent.handle
- this._store = parent._store
- this._selection = parent._selection
- this.parent = parent
- this.icons = parent.icons
- this.myIter = bmx_gtk3_gtktreeiter_new()
- this.refreshPath(index)
-
- Return this
- End Function
- Method refreshPath(index:Int)
- Assert myIter, "Null Iterator!"
-
- If parent Then
- _path = TGTKTreeViewNode(parent)._path
- If TGTKTreeViewNode(parent)._path.length > 0 Then
- _path:+ ":"
- End If
- Else
- _path = ""
- End If
- _path:+ index
- gtk_tree_model_get_iter_from_string(_store, myIter, _path)
- End Method
- Method refreshChildPaths()
- Local i:Int = 0
- For Local child:TGTKTreeViewNode = EachIn kids
- child.refreshPath(i)
- child.refreshChildPaths()
- i:+ 1
- Next
- End Method
- Function OnSelectionChanged(_sel:Byte Ptr, obj:Object)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local node:TGTKTreeViewNode = Null
- Local selected:Int = gtk_tree_selection_get_selected(_sel, Null, iter)
- If selected Then
- Local p:Byte Ptr = gtk_tree_model_get_string_from_iter(TGTKList(obj)._store, iter)
- node = TGTKTreeViewNode(obj).findNodeFromPath(String.FromCString(p))
- g_free(p)
- End If
- If Not TGTKList(obj).ignoreListChangeEvent Then
- PostGuiEvent(EVENT_GADGETSELECT, TGadget(obj),,,,,node)
- End If
- TGTKList(obj).ignoreListChangeEvent = False
- bmx_gtk3_gtktreeiter_free(iter)
- End Function
- Rem
- bbdoc: Returns the root node for this tree
- End Rem
- Method RootNode:TGadget()
- If Not isRoot Then
- Return parent.RootNode()
- End If
- Return Self
- End Method
- Rem
- bbdoc: Inserts a new node as a child at the specified index.
- End Rem
- Method InsertNode:TGadget(index:Int, text:String, icon:Int)
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- Local childNode:TGTKTreeViewNode
- ' create a new row in the tree
- If isRoot Then
- If index < 0 Then
- gtk_tree_store_append(_store, iter, Null)
- Else
- gtk_tree_store_insert(_store, iter, Null, index)
- End If
- Else
- If index < 0 Then
- gtk_tree_store_append(_store, iter, myIter)
- Else
- gtk_tree_store_insert(_store, iter, myIter, index)
- End If
- End If
- ' add the text / icon to the tree
- populateListRow(index, text, Null, icon, iter)
- ' add the child to the parent kids
- If index < 0 Or index = CountKids() Then
- childNode = TGTKTreeViewNode._createNode(Self, CountKids())
- childNode._text = text
- kids.addLast(childNode)
- Else
- childNode = TGTKTreeViewNode._createNode(Self, index)
- childNode._text = text
- TEList(kids).insertElementAt(childNode, index)
- refreshChildPaths()
- End If
- childNode._icon = icon
-
- If (LocalizationMode() & LOCALIZATION_OVERRIDE) Then
- LocalizeGadget(childNode, text)
- Else
- childNode.SetText(text)
- EndIf
- bmx_gtk3_gtktreeiter_free(iter)
- Return childNode
- End Method
- Rem
- bbdoc: Changes the tree node text and icon
- End Rem
- Method ModifyNode:Int(text:String, icon:Int)
- ' not allowed to modify the root node... quietly ignore the request.
- If isRoot Then
- Return 0
- End If
- _text = text
- populateListRow(-1, text, Null, icon, myIter)
- End Method
- Rem
- bbdoc: Returns the currently selected tree node or null if none selected
- End Rem
- Method SelectedNode:TGadget()
- Local iter:Byte Ptr = bmx_gtk3_gtktreeiter_new()
- If gtk_tree_selection_get_selected(_selection, Null, iter) Then
- Local path:Byte Ptr = gtk_tree_model_get_path(_store, iter)
- Local p:Byte Ptr = gtk_tree_path_to_string(path)
- Local node:TGTKTreeViewNode = findNodeFromPath(String.FromCString(p))
- g_free(p)
- gtk_tree_path_free(path)
-
- bmx_gtk3_gtktreeiter_free(iter)
- Return node
- End If
- bmx_gtk3_gtktreeiter_free(iter)
- Return Null
- End Method
- Rem
- bbdoc: Returns the number of child nodes
- End Rem
- Method CountKids:Int()
- Return kids.count()
- End Method
- Method free:Int() Override
- Super.free()
- If isRoot Then
- If scrollWindow Then
- gtk_widget_destroy(scrollWindow)
- End If
- scrollWindow = Null
- handle = Null
- Else
- ' this should always be true... if not, we really want to throw an assertion.
- ' Assert myIter, "Trying to Free() a node twice?"
- If myIter Then
- gtk_tree_store_remove(_store, myIter)
- bmx_gtk3_gtktreeiter_free(myIter)
- myIter = Null
- If parent Then
- TGTKTreeViewNode(parent).refreshChildPaths()
- End If
- End If
- End If
-
- End Method
- ' search always begins from the tree root, so we only need to look through the
- ' children.. ie. downwards
- ' TODO : make this more efficient... we should be able to use the path to skip
- ' searching of child nodes of nodes not in our path
- Method findNodeFromPath:TGTKTreeViewNode(lookup:String)
- If lookup = _path Then
- Return Self
- End If
- Local i:Int = 0
- For Local child:TGTKTreeViewNode = EachIn kids
- Local node:TGTKTreeViewNode = child.findNodeFromPath(lookup)
- If node Then
- Return node
- End If
- Next
- Return Null
- End Method
- Method Activate:Int(command:Int)
- Super.Activate(command)
- Select command
- Case ACTIVATE_EXPAND
- If _path <> Null And _path.length > 0 Then
- ignoreExpand = True
- ' get the tree view
- Local _root:TGTKTreeViewNode = TGTKTreeViewNode(RootNode())
- ' get this node path
- Local path:Byte Ptr = gtk_tree_path_new_from_string(_path)
-
- ' expand the node
- gtk_tree_view_expand_row(_root.handle, path, False)
-
- ' free stuff
- gtk_tree_path_free(path)
- End If
- Case ACTIVATE_COLLAPSE
- If _path <> Null And _path.length > 0 Then
- ignoreCollapse = True
- ' get the tree view
- Local _root:TGTKTreeViewNode = TGTKTreeViewNode(RootNode())
- ' get this node path
- Local path:Byte Ptr = gtk_tree_path_new_from_string(_path)
-
- ' expand the node
- gtk_tree_view_collapse_row(_root.handle, path)
-
- ' free stuff
- gtk_tree_path_free(path)
- End If
- Case ACTIVATE_SELECT
- If _path <> Null And _path.length > 0 Then
- ' the tree view should ignore this selection...
- TGTKTreeViewNode(RootNode()).ignoreListChangeEvent = True
-
- ' get this node path
- Local path:Byte Ptr = gtk_tree_path_new_from_string(_path)
-
- ' set the new selection
- gtk_tree_selection_select_path(_selection, path)
-
- ' free stuff
- gtk_tree_path_free(path)
- End If
- End Select
- End Method
-
- Rem
- bbdoc: Returns the text for this node.
- End Rem
- Method GetText:String()
- Return _text
- End Method
-
- Rem
- bbdoc: Sets the text for this node.
- End Rem
- Method SetText:Int(text:String)
- ModifyNode(text, _icon)
- End Method
- Method toString:String()
- Return "TGTKTreeViewNode : " + _text + " : " + Super.ToString()
- End Method
-
- End Type
- Rem
- bbdoc: A tree view.
- End Rem
- Type TGTKTreeView Extends TGTKTreeViewNode
- Function CreateTreeView:TGTKTreeView(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKTreeView = New TGTKTreeView
- this.initTreeView(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initTreeView(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Init(GTK_TREEVIEW, x, y, w, h, style)
- ignoreListChangeEvent = True
-
- kids = New TEList
- ' create the tree store
- _store = gtk_tree_store_new(2, gdk_pixbuf_get_type(), G_TYPE_STRING)
- ' set up the column contents
- initColumns()
- ' attach store to the view
- gtk_tree_view_set_model(handle, _store)
- ' remove *our* reference to the store... when the tree is destroyed this will be too
- g_object_unref(_store)
- SetShow(True)
- gtk_layout_put(TGTKContainer(group).container, scrollwindow, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- addConnection("row-activated", g_signal_cb4(handle, "row-activated", OnRowActivated, Self, Destroy, 0))
- addConnection("row-expanded", g_signal_cb4(handle, "row-expanded", OnRowExpanded, Self, Destroy, 0))
- addConnection("row-collapsed", g_signal_cb4(handle, "row-collapsed", OnRowCollapsed, Self, Destroy, 0))
- isRoot = True
- End Method
- Rem
- bbdoc: Callback For tree-view node activation (Double-click).
- End Rem
- Function OnRowActivated(widget:Byte Ptr, treePath:Byte Ptr, treeviewColumn:Byte Ptr, obj:Object)
- Local p:Byte Ptr = gtk_tree_path_to_string(treePath)
- Local node:TGTKTreeViewNode = TGTKTreeViewNode(obj).findNodeFromPath(String.FromCString(p))
- ' clean up mem
- g_free(p)
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj),,,,,node)
- End Function
- Rem
- bbdoc: Callback for tree-view node expand.
- End Rem
- Function OnRowExpanded(widget:Byte Ptr, treeIter:Byte Ptr, treePath:Byte Ptr, obj:Object)
- Local p:Byte Ptr = gtk_tree_path_to_string(treePath)
- Local node:TGTKTreeViewNode = TGTKTreeViewNode(obj).findNodeFromPath(String.FromCString(p))
- ' clean up mem
- g_free(p)
- If Not node.ignoreExpand Then
- PostGuiEvent(EVENT_GADGETOPEN, TGadget(obj),,,,,node)
- End If
- node.ignoreExpand = False
- End Function
- Rem
- bbdoc: Callback for tree-view node collapse.
- End Rem
- Function OnRowCollapsed(widget:Byte Ptr, treeIter:Byte Ptr, treePath:Byte Ptr, obj:Object)
- Local p:Byte Ptr = gtk_tree_path_to_string(treePath)
- Local node:TGTKTreeViewNode = TGTKTreeViewNode(obj).findNodeFromPath(String.FromCString(p))
- ' clean up mem
- g_free(p)
- If Not node.ignoreCollapse Then
- PostGuiEvent(EVENT_GADGETCLOSE, TGadget(obj),,,,,node)
- End If
- node.ignoreCollapse = False
- End Function
- Rem
- bbdoc: Callback for mouse right-click
- End Rem
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then ' right mouse button
-
- Local node:TGTKTreeViewNode
- Local treePath:Byte Ptr
-
- ' Get tree path For row that was clicked
- If gtk_tree_view_get_path_at_pos(widget, Int(x), Int(y), Varptr treePath, Null, Null, Null) Then
- Local p:Byte Ptr = gtk_tree_path_to_string(treePath)
- node = TGTKTreeViewNode(obj).findNodeFromPath(String.FromCString(p))
-
- ' clean up mem
- g_free(p)
- gtk_tree_path_free(treePath)
- End If
-
- PostGuiEvent(EVENT_GADGETMENU, TGadget(obj),,,Int(x),Int(y),node)
- Return True
- End If
- Return False
- End Function
-
- ' overriden - does nothing!!
- Method LayoutKids:Int()
- End Method
- Method rethink:Int()
- If handle Then
- gtk_layout_move(TGTKContainer(parent).container, scrollwindow, Max(xpos, 0), Max(ypos, 0))
- gtk_widget_set_size_request(scrollwindow, Max(width,0), Max(height,0))
- End If
- End Method
- Method toString:String()
- Return "TGTKTreeView"
- End Method
- End Type
- Rem
- bbdoc: A base-type for handling slider / range gadgets - ScrollBar and TrackBar
- End Rem
- Type TGTKRange Extends TGTKGadget
- Field currentValue:Int
- Field rangeMin:Int
- Field rangeMax:Int
- Rem
- bbdoc: Sets the slider range.
- End Rem
- Method SetRange:Int(visible:Int, total:Int)
- rangeMin = Min(visible, total)
- rangeMax = Max(visible, total)
- gtk_range_set_range(handle, rangeMin, rangeMax)
- End Method
- Rem
- bbdoc: Sets the value on the slider.
- End Rem
- Method SetProp:Int(value:Int)
- currentValue = value
- gtk_range_set_value(handle, value)
- End Method
- Rem
- bbdoc: Returns the current slider value.
- End Rem
- Method GetProp:Int()
- Return gtk_range_get_value(handle)
- End Method
- Rem
- bbdoc: Callback for user changing of a slider.
- about: Tries to keep the value within the desired range.
- End Rem
- Function OnChangeValue:Int(widget:Byte Ptr, scrolltype:Int, value:Double, obj:Object)
- Local v:Int = Max(Min(value, TGTKRange(obj).rangeMax), TGTKRange(obj).rangeMin)
- If v <> TGTKRange(obj).currentValue Then
- TGTKRange(obj).currentValue = v
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), v)
- End If
- Return False
- End Function
-
- Method free:Int() Override
- Super.Free()
- If handle
- gtk_widget_destroy(handle)
- EndIf
- handle = Null
- End Method
- Method toString:String()
- Return "TGTKRange"
- End Method
- End Type
- Rem
- bbdoc: A scrollbar
- End Rem
- Type TGTKScrollBar Extends TGTKRange
- Field thumbSize:Int
- Field Range:Int
- Field pageSize:Int
- Function CreateScrollBar:TGTKScrollBar(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKScrollBar = New TGTKScrollBar
- this.initScrollBar(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initScrollBar(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- If style & SLIDER_VERTICAL Then
- handle = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, Null)
- Else
- handle = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, Null)
- End If
- Init(GTK_SCROLLBAR, x, y, w, h, style)
- ' set the default range
- SetRange(1, 10)
- setShow(True)
- addConnection("change-value", g_signal_cb4a(handle, "change-value", OnChangeValue, Self, Destroy, 0))
-
- gtk_layout_put(TGTKContainer(group).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- gtk_range_set_round_digits(handle, 0)
- End Method
- Rem
- bbdoc: Overrides the default...
- End Rem
- Method SetRange:Int(small:Int, big:Int)
- Range = big - small
- pageSize = small
-
- If small <> 0 Then
- thumbSize = big/small
- thumbSize = range / thumbSize
- Else
- thumbSize = 1
- End If
- If Range = 0 Then
- Range = 1
- thumbSize = 1
- End If
- gtk_adjustment_set_page_size(gtk_range_get_adjustment(handle), thumbSize)
- gtk_range_set_increments(handle, 1, pageSize)
- gtk_range_set_range(handle, 0, Range)
- gtk_range_set_value(handle, GetProp())
- End Method
- Function OnChangeValue:Int(widget:Byte Ptr, scrolltype:Int, value:Double, obj:Object)
- Local v:Int = Min(TGTKScrollBar(obj).range, Max(value, 0))
- If v <> TGTKRange(obj).currentValue Then
- TGTKRange(obj).currentValue = v
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), v)
- End If
- Return False
- End Function
- Method toString:String()
- Return "TGTKScrollBar"
- End Method
- End Type
- Rem
- bbdoc: A trackbar
- End Rem
- Type TGTKTrackBar Extends TGTKRange
- Function CreateTrackBar:TGTKTrackBar(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKTrackBar = New TGTKTrackBar
- this.initTrackBar(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initTrackBar(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- If style & SLIDER_VERTICAL Then
- handle = gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL, 1, 10, 1)
- Else
- handle = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 1, 10, 1)
- End If
- Init(GTK_TRACKBAR, x, y, w, h, style)
- ' set the default range
- SetRange(1,10)
- gtk_scale_set_draw_value(handle, False)
- setShow(True)
-
- addConnection("change-value", g_signal_cb4a(handle, "change-value", OnChangeValue, Self, Destroy, 0))
- gtk_layout_put(TGTKContainer(group).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- End Method
- Method toString:String()
- Return "TGTKTrackBar"
- End Method
- End Type
- Type TGTKStepper Extends TGTKGadget
- Function CreateStepper:TGTKStepper(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKStepper = New TGTKStepper
- this.initStepper(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initStepper(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
-
- handle = gtk_spin_button_new_with_range(1, 100, 1)
-
- Init(GTK_STEPPER, x, y, w, h, style)
-
- ' init range..
- SetRange(1,100)
- gtk_spin_button_set_increments(handle, 1, 10)
-
- setShow(True)
-
- addConnection("change-value", g_signal_cb3a_ret(handle, "change-value", OnChangeValue, Self, Destroy, 0))
- gtk_layout_put(TGTKContainer(group).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- End Method
- Rem
- bbdoc: Sets the value on the slider.
- End Rem
- Method SetProp:Int(value:Int)
- 'currentValue = value
- gtk_spin_button_set_value(handle, value)
- End Method
- Rem
- bbdoc: Returns the current slider value.
- End Rem
- Method GetProp:Int()
- Return gtk_spin_button_get_value(handle)
- End Method
- Rem
- bbdoc: Sets the slider range.
- End Rem
- Method SetRange:Int(visible:Int, total:Int)
- Local rangeMin:Int = Min(visible, total)
- Local rangeMax:Int = Max(visible, total)
- gtk_spin_button_set_range(handle, rangeMin, rangeMax)
- End Method
- Function OnChangeValue:Int(widget:Byte Ptr, scrolltype:Int, obj:Object)
- Local v:Int = gtk_spin_button_get_value(widget)
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), v)
- Return False
- End Function
- Method toString:String()
- Return "TGTKStepper"
- End Method
- End Type
- Rem
- bbdoc: A progress bar
- about: Interestingly, although we can find out the current value, MaxGUI doesn't support it...
- End Rem
- Type TGTKProgressBar Extends TGTKGadget
- Field ebox:Byte Ptr
- Function CreateProgressBar:TGTKProgressBar(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKProgressBar = New TGTKProgressBar
- this.initProgressBar(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initProgressBar(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- handle = gtk_progress_bar_new()
-
- Init(GTK_PROGRESSBAR, x, y, w, h, style)
- ' required for tooltips functionality
- gtk_widget_add_events(handle, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK)
- setShow(True)
- gtk_layout_put(TGTKContainer(group).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- End Method
- Rem
- bbdoc: Set the value of the progress bar.
- End Rem
- Method SetValue:Int(value:Float)
- value = Min(Max(0, value), 1.0)
- gtk_progress_bar_set_fraction(handle, value)
- End Method
-
- Rem
- bbdoc: Get the current value of the progress bar
- End Rem
- Method GetValue:Float()
- Return gtk_progress_bar_get_fraction(handle)
- End Method
-
- Method free:Int() Override
- Super.Free()
- If handle
- gtk_widget_destroy(handle)
- EndIf
- handle = Null
- End Method
- Method toString:String()
- Return "TGTKProgressBar"
- End Method
- End Type
- Rem
- bbdoc: A Toolbar
- End Rem
- Type TGTKToolbar Extends TGTKGadget
- Field icons:TGTKIconStrip
- Field toolitems:Byte Ptr[]
- Function CreateToolBar:TGTKToolbar(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKToolbar = New TGTKToolbar
- this.initToolbar(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initToolbar(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- handle = gtk_toolbar_new()
- Init(GTK_TOOLBAR, x, y, w, h, style)
- If TGTKWindow(group) Then
- TGTKWindow(group).addToolbar(Self)
- End If
- ' show icons only
- gtk_toolbar_set_style(handle, GTK_TOOLBAR_ICONS)
- gtk_widget_show(handle)
- End Method
- Method SetIconStrip:Int(iconstrip:TIconStrip)
- icons = TGTKIconStrip(iconstrip)
- End Method
- Rem
- bbdoc: Inserts an item at the specified index.
- End Rem
- Method InsertListItem:Int(index:Int, text:String, tip:String, icon:Int, extra:Object)
- Local image:Byte Ptr
- If icons And icon>=0 Then
- image = icons.images[icon]
- End If
- toolitems = toolitems[..toolitems.length+1]
- For Local i:Int = toolitems.length - 2 To index Step -1
- toolitems[i + 1] = toolitems[i]
- Next
- If image Then
- Local imageWidget:Byte Ptr = gtk_image_new_from_pixbuf(image)
- gtk_widget_show(imageWidget)
-
- Local textPtr:Byte Ptr = text.ToUTF8String()
- If items[index].flags = GADGETITEM_TOGGLE Then
- toolitems[index] = gtk_toggle_tool_button_new()
- gtk_tool_button_set_label(toolitems[index], textPtr)
- gtk_tool_button_set_icon_name(toolitems[index], icons.names[icon])
- addConnection("toggled", g_signal_cb2(toolitems[index], "toggled", OnToolItemToggled, Self, Destroy, 0))
- Else
- toolitems[index] = gtk_tool_button_new(Null, textPtr)
- gtk_tool_button_set_label(toolitems[index], textPtr)
- gtk_tool_button_set_icon_name(toolitems[index], icons.names[icon])
-
- addConnection("clicked", g_signal_cb2(toolitems[index], "clicked", OnToolItemClicked, Self, Destroy, 0))
- End If
- MemFree(textPtr)
- ' Add a tooltip
- SetToolTipIndex(index, tip)
- Else
- ' no image? Then this is a separator!
- toolitems[index] = gtk_separator_tool_item_new()
- End If
- gtk_widget_show(toolitems[index])
- gtk_toolbar_insert(handle, toolitems[index], index)
- End Method
- Function OnToolItemToggled(widget:Byte Ptr, obj:Object)
- Local index:Int = gtk_toolbar_get_item_index(TGTKToolbar(obj).handle, widget)
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), index, gtk_toggle_tool_button_get_active(widget))
- End Function
- Function OnToolItemClicked(widget:Byte Ptr, obj:Object)
- Local index:Int = gtk_toolbar_get_item_index(TGTKToolbar(obj).handle, widget)
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), index)
- End Function
- Method SetListItem:Int(index:Int, text:String, tip:String, icon:Int, extra:Object)
- If toolitems[index] Then
- gtk_container_remove(handle, toolitems[index])
- For Local i:Int = index Until toolitems.length - 1
- toolitems[i] = toolitems[i + 1]
- Next
- toolitems = toolitems[..toolitems.length - 1]
- End If
- InsertListItem(index, text, tip, icon, extra)
- End Method
- Method SetToolTipIndex:Int(index:Int, tip:String)
- ' Add a tooltip
- If tip And tip.length > 0 Then
- Local tipPtr:Byte Ptr = tip.ToUTF8String()
- gtk_tool_item_set_tooltip_text(toolitems[index], tipPtr)
- MemFree(tipPtr)
- Else
- gtk_tool_item_set_tooltip_text(toolitems[index], Null)
- End If
- End Method
- Method SetListItemState:Int(item:Int, state:Int)
- If state & STATE_DISABLED Then
- gtk_widget_set_sensitive(toolitems[item], False)
- Else
- gtk_widget_set_sensitive(toolitems[item], True)
- End If
- If items[item].flags = GADGETITEM_TOGGLE Then
- If state & STATE_SELECTED Then
- gtk_toggle_tool_button_set_active(toolitems[item], True)
- Else
- gtk_toggle_tool_button_set_active(toolitems[item], False)
- End If
- End If
-
- gtk_widget_queue_draw(handle)
- End Method
- Method ListItemState:Int(index:Int)
- Local state:Int = 0
- If Not gtk_widget_is_sensitive(toolitems[index]) Then
- state:| STATE_DISABLED
- End If
- If items[index].flags = GADGETITEM_TOGGLE Then
- If gtk_toggle_tool_button_get_active(toolitems[index]) Then
- state:| STATE_SELECTED
- End If
- End If
- Return state
- End Method
- Method RemoveListItem:Int(index:Int)
- If toolitems[index] Then
- gtk_container_remove(handle, toolitems[index])
- For Local i:Int = index Until toolitems.length - 1
- toolitems[i] = toolitems[i + 1]
- Next
- toolitems = toolitems[..toolitems.length - 1]
- End If
- End Method
- Method rethink:Int()
- End Method
- Method free:Int() Override
- Super.Free()
- If handle
- gtk_widget_destroy(handle)
-
- ' assuming that destroying the toolbar will destroy
- For Local i:Int = 0 Until toolitems.length
- toolitems[i] = Null
- Next
- EndIf
- handle = Null
- End Method
- Method toString:String()
- Return "TGTKToolbar"
- End Method
- End Type
- Rem
- bbdoc: A tabber.
- End Rem
- Type TGTKTabber Extends TGTKContainer
- Field icons:TGTKIconStrip
- Field images:Byte Ptr[]
- Field labels:Byte Ptr[]
- Field pages:Byte Ptr[]
- Field ignoreChange:Int
- Field currentIndex:Int = -1
- Function CreateTabber:TGTKTabber(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKTabber = New TGTKTabber
- this.initTabber(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initTabber(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- handle = gtk_notebook_new()
- Init(GTK_TABBER, x, y, w, h, style)
- container = gtk_layout_new(Null, Null)
- gtk_widget_show(container)
- g_object_ref(container) ' hold an extra ref for our container
- ' Scrollable tabs if there are too many to fit on the display
- gtk_notebook_set_scrollable(handle, True)
- gtk_widget_show(handle)
- g_signal_tabchange(handle, "switch-page", OnTabChanged, Self, Destroy, 0)
- gtk_layout_put(TGTKContainer(group).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- End Method
- Function OnTabChanged(widget:Byte Ptr, page:Byte Ptr, index:Int, obj:Object)
- If TGTKTabber(obj).currentIndex >= 0 Then
- Local child:Byte Ptr = gtk_notebook_get_nth_page(TGTKTabber(obj).handle, TGTKTabber(obj).currentIndex)
- TGTKTabber(obj).RemoveFromTab(child)
- End If
-
- If index >= 0 Then
- TGTKTabber(obj).AddToTab(page)
- End If
- TGTKTabber(obj).currentIndex = index
- If Not TGTKTabber(obj).ignoreChange Then
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj), index,,,,TGadget(obj).ItemExtra(index))
- End If
- TGTKTabber(obj).ignoreChange = False
- End Function
- Rem
- bbdoc: Inserts a new tab
- End Rem
- Method InsertListItem:Int(index:Int, text:String, tip:String, icon:Int, tag:Object)
- ' don't create gui events when inserting new pages.
- ignoreChange = True
-
- Local image:Byte Ptr
- If icons And icon>=0 Then
- image = icons.images[icon]
- End If
- images = images[..images.length+1]
- For Local i:Int = images.length - 2 To index Step -1
- images[i + 1] = images[i]
- Next
- labels = labels[..labels.length+1]
- For Local i:Int = labels.length - 2 To index Step -1
- labels[i + 1] = labels[i]
- Next
-
- pages = pages[..pages.length+1]
- For Local i:Int = pages.length - 2 To index Step -1
- pages[i + 1] = pages[i]
- Next
- If image Then
- images[index] = gtk_image_new_from_pixbuf(image)
- gtk_widget_show(images[index])
- Else
- images[index] = gtk_image_new()
- End If
- ' since a Label can't accept events, we wrap it inside an event box which can
- Local box:Byte Ptr = gtk_event_box_new()
- gtk_event_box_set_visible_window(box, False)
- gtk_widget_add_events(box, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK)
- ' show the box
- gtk_widget_show(box)
-
- ' create a display label for the tab
- Local textPtr:Byte Ptr = text.ToUTF8String()
- labels[index] = gtk_label_new(textPtr)
- MemFree(textPtr)
- gtk_widget_show(labels[index])
-
- ' create a horizontal box to place the image/label combo
- Local hbox:Byte Ptr = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4)
- gtk_widget_show(hbox)
-
- ' add widgets to the hbox
- gtk_box_pack_start(hbox, images[index], False, False, 0)
- gtk_box_pack_start(hbox, labels[index], False, False, 0)
-
- ' add the hbox to the eventbox
- gtk_container_add(box, hbox)
- ' create a child to hold our container.
- Local child:Byte Ptr = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0)
- pages[index] = child
- gtk_widget_show(child)
- gtk_notebook_insert_page(handle, child, box, index)
- ' Add a tooltip to the event box
- SetToolTipIndex(index, tip, box)
- End Method
- Method SetListItem:Int(index:Int, text:String, tip:String, icon:Int, tag:Object)
- Local child:Byte Ptr = gtk_notebook_get_nth_page(handle, index)
-
- ' get the event box to which we set tooltips
- Local box:Byte Ptr = gtk_notebook_get_tab_label(handle, child)
- ' is there an image to show?
- Local image:Byte Ptr
- If icons And icon>=0 Then
- image = icons.images[icon]
- End If
- If Not image Then
- ' hide image if none
- gtk_widget_hide(images[index])
- Else
- ' set and display image
- gtk_image_set_from_pixbuf(images[index], image)
- gtk_widget_show(images[index])
- End If
- ' set new text
- Local textPtr:Byte Ptr = text.ToUTF8String()
- gtk_label_set_text(labels[index], textPtr)
- MemFree(textPtr)
-
- ' Add a tooltip to the event box
- SetToolTipIndex(index, tip, box)
- End Method
- Method RemoveListItem:Int(index:Int)
- Local arr:Byte Ptr[] = images
- images = images[..images.length-1]
- For Local i:Int = index To arr.length-2
- images[i] = arr[i+1]
- Next
- arr = labels
- labels = labels[..labels.length-1]
- For Local i:Int = index To arr.length-2
- labels[i] = arr[i+1]
- Next
- arr = pages
- pages = pages[..pages.length-1]
- For Local i:Int = index To arr.length-2
- pages[i] = arr[i+1]
- Next
- ' remove from current tab if required
- If gtk_notebook_get_current_page(handle) = index Then
- Local child:Byte Ptr = gtk_notebook_get_nth_page(handle, index)
- RemoveFromTab(child)
- currentIndex = -1
- Else If index < currentIndex Then
- currentIndex :- 1
- End If
-
- gtk_notebook_remove_page(handle, index)
-
- End Method
- Method ListItemState:Int(index:Int)
- Local state:Int = 0
- If gtk_notebook_get_current_page(handle) = index Then
- state:| STATE_SELECTED
- End If
- Return state
- End Method
- Method SetListItemState:Int(index:Int, state:Int)
- If state & STATE_SELECTED Then
- If gtk_notebook_get_current_page(handle) <> index Then
- ignoreChange = True
- ?bmxng
- IWrappedSystemDriver(SystemDriver()).GetDriver().Poll()
- ?Not bmxng
- brl.System.Driver.Poll() ' update events
- ?
- gtk_notebook_set_current_page(handle, index)
- End If
- End If
- End Method
- Method ClientHeight:Int()
- Local h:Int = height
- If handle Then
- ?bmxng
- Local minReq:GtkRequisition
- Local natReq:GtkRequisition
- ?Not bmxng
- Local minReq:GtkRequisition = New GtkRequisition
- Local natReq:GtkRequisition = New GtkRequisition
- ?
- gtk_widget_get_preferred_size(handle, minReq, natReq)
- h :- 34 ' FIXME : current hard-coded. Should be height of notebook less tab height and border.
- End If
- Return Max(0, h)
- End Method
- Method ClientWidth:Int()
- Local w:Int = width
- If handle Then
- ?bmxng
- Local minReq:GtkRequisition
- Local natReq:GtkRequisition
- ?Not bmxng
- Local minReq:GtkRequisition = New GtkRequisition
- Local natReq:GtkRequisition = New GtkRequisition
- ?
- gtk_widget_get_preferred_size(handle, minReq, natReq)
- w:- 4 ' FIXME : current hard-coded. Should be width of notebook less borders.
- End If
- Return Max(0, w)
- End Method
- Method SetToolTipIndex:Int(index:Int, tip:String, label:Byte Ptr)
- ' Add a tooltip
- If tip And tip.length > 0 Then
- Local tipPtr:Byte Ptr = tip.ToUTF8String()
- gtk_widget_set_tooltip_text(label, tipPtr)
- MemFree(tipPtr)
- Else
- gtk_widget_set_tooltip_text(label, Null)
- End If
- End Method
- Method SetIconStrip:Int(iconstrip:TIconStrip)
- icons = TGTKIconStrip(iconstrip)
- End Method
- Method free:Int() Override
- Super.Free()
-
- If container Then
- gtk_widget_destroy(container)
- container = Null
- End If
- handle = Null
- images = Null
- labels = Null
- End Method
- Method Rethink:Int()
- If handle Then
- gtk_layout_move(TGTKContainer(parent).container, handle, xpos, ypos)
- gtk_widget_set_size_request(handle, Max(width,0), Max(height,0))
- End If
- End Method
- Method toString:String()
- Return "TGTKTabber"
- End Method
-
- Method RemoveFromTab(page:Byte Ptr)
- If currentIndex >= 0 Then
- g_object_ref(container)
- gtk_container_remove(page, container)
- End If
- End Method
- Method AddToTab(page:Byte Ptr)
- gtk_box_pack_start(page, container, True, True, 0)
- g_object_unref(container)
- End Method
- End Type
- Rem
- bbdoc: A Panel
- End Rem
- Type TGTKPanel Extends TGTKContainer
- Field frame:Byte Ptr
- Field hasFrame:Int
- Field panelPixmap:TPixmap
- Field panelPixbuf:Byte Ptr
- Field pixmapMode:Int
-
- Field drawPixbuf:Int
- Field visualpixbuf:Byte Ptr
- Field pbx:Int
- Field pby:Int
-
- Field pane:Int
- Function CreatePanel:TGTKPanel(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int, intoPane:Int = 0)
- Local this:TGTKPanel = New TGTKPanel
- this.initPanel(x, y, w, h, label, group, style, intoPane)
- Return this
- End Function
- Method initPanel(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int, intoPane:Int)
- handle = gtk_layout_new(Null, Null)
- Init(GTK_PANEL, x, y, w, h, style)
- container = handle
-
- If style & PANEL_ACTIVE
- sensitivity:| SENSITIZE_MOUSE | SENSITIZE_KEYS
- End If
- gtk_widget_add_events(handle, GDK_BUTTON_PRESS_MASK | ..
- GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | ..
- GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK)' | ..
- ' GDK_POINTER_MOTION_HINT_MASK)
- addConnection("button-press-event", g_signal_cb3_ret(handle, "button-press-event", OnMouseDown, Self, Destroy, 0))
- addConnection("button-release-event", g_signal_cb3_ret(handle, "button-release-event", OnMouseUp, Self, Destroy, 0))
- addConnection("enter-notify-event", g_signal_cb3_ret(handle, "enter-notify-event", OnMouseEnter, Self, Destroy, 0))
- addConnection("leave-notify-event", g_signal_cb3_ret(handle, "leave-notify-event", OnMouseLeave, Self, Destroy, 0))
- addConnection("motion-notify-event", g_signal_cb3_ret(handle, "motion-notify-event", OnMouseMove, Self, Destroy, 0))
- addConnection("draw", g_signal_cb3_ret(handle, "draw", OnDraw, Self, Destroy, 0))
- addConnection("scroll-event", g_signal_cb3(handle, "scroll-event", OnScroll, Self, Destroy, 0))
- addConnection("key-press-event", g_signal_cb3_ret(handle, "key-press-event", OnKeyDown, Self, Destroy, 0))
- addConnection("key-release-event", g_signal_cb3_ret(handle, "key-release-event", OnKeyUp, Self, Destroy, 0))
- gtk_widget_show(handle)
- ' Should we add a frame?
- If style & PANEL_BORDER Or style & PANEL_GROUP Then
- hasFrame = True
- frame = gtk_frame_new(Null)
- gtk_widget_show(frame)
- ' set frame text
- If (LocalizationMode() & LOCALIZATION_OVERRIDE) Then
- LocalizeGadget(Self, label)
- Else
- SetText(label)
- EndIf
-
- gtk_container_add(frame, handle)
- gtk_layout_put(TGTKContainer(group).container, frame, x, y)
- gtk_widget_set_size_request(frame, w, Max(h,0))
- Else
- gtk_layout_put(TGTKContainer(group).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- End If
- End Method
- Rem
- bbdoc: Callback for mouse button press.
- End Rem
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKPanel(obj).style & PANEL_ACTIVE Then
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then
- button = 2
- Else If button = 2 Then
- button = 3
- End If
- PostGuiEvent(EVENT_MOUSEDOWN, TGadget(obj),button,,Int(x),Int(y))
- End If
- Return True
- End Function
- Rem
- bbdoc: Callback for mouse button release.
- End Rem
- Function OnMouseUp:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKPanel(obj).style & PANEL_ACTIVE Then
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then
- button = 2
- Else If button = 2 Then
- button = 3
- End If
-
- PostGuiEvent(EVENT_MOUSEUP, TGadget(obj),button,,Int(x),Int(y))
- End If
- Return True
- End Function
- Rem
- bbdoc: Callback for mouse enter.
- End Rem
- Function OnMouseEnter:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKPanel(obj).style & PANEL_ACTIVE Then
- If TGTKGadget(obj).visible Then
- PostGuiEvent(EVENT_MOUSEENTER, TGadget(obj))
- End If
- End If
- Return False
- End Function
- Rem
- bbdoc: Callback for mouse leave.
- End Rem
- Function OnMouseLeave:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKPanel(obj).style & PANEL_ACTIVE Then
- If TGTKGadget(obj).visible Then
- PostGuiEvent(EVENT_MOUSELEAVE, TGadget(obj))
- End If
- End If
- Return False
- End Function
- Rem
- bbdoc: Callback for mouse movement
- End Rem
- Function OnMouseMove:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKPanel(obj).style & PANEL_ACTIVE Then
- Local _x:Double, _y:Double, button:Int
- bmx_gtk3maxgui_gdkeventmotion(event, Varptr _x, Varptr _y, Varptr button)
- Local x:Int, y:Int
-
- ' we actually ignore the coords returned by the event and get the
- ' mouse coords relative to this widget's parent
- gdk_window_get_device_position(gtk_widget_get_parent_window(widget), bmx_gtk3maxgui_gdkeventmotiondevice(event), x, y, button)
- ' then we remove the stored coords from that value to get the TRUE coords.
- x:- TGTKPanel(obj).xpos
- y:- TGTKPanel(obj).ypos
-
- If button & GDK_BUTTON1_MASK Then
- button = 1
- Else If button & GDK_BUTTON3_MASK Then
- button = 2
- Else If button & GDK_BUTTON2_MASK Then
- button = 3
- Else
- button = 0
- End If
- PostGuiEvent(EVENT_MOUSEMOVE, TGadget(obj),button,,x,y)
- End If
- Return True
- End Function
- Function OnDraw:Int(widget:Byte Ptr, cairo:Byte Ptr, obj:Object)
- Local panel:TGTKPanel = TGTKPanel(obj)
- If panel Then
- If panel.drawPixbuf And panel.visualpixbuf Then
- gdk_cairo_set_source_pixbuf(cairo, panel.visualpixbuf, panel.pbx, panel.pby)
- cairo_paint(cairo)
- cairo_fill(cairo)
- End If
- End If
- PostGuiEvent(EVENT_GADGETPAINT, TGadget(obj))
- End Function
-
- Rem
- bbdoc: Callback for mouse scroll wheel
- End Rem
- Function OnScroll(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKPanel(obj).style & PANEL_ACTIVE Then
- Local x:Double, y:Double, direction:Int
- bmx_gtk3maxgui_gdkeventscroll(event, Varptr x, Varptr y, Varptr direction)
- If direction = GDK_SCROLL_UP Or direction = GDK_SCROLL_LEFT Then
- PostGuiEvent(EVENT_MOUSEWHEEL, TGadget(obj),-1,,Int(x),Int(y))
- Else
- PostGuiEvent(EVENT_MOUSEWHEEL, TGadget(obj),1,,Int(x),Int(y))
- End If
- End If
- End Function
- Rem
- bbdoc: Callback for key down
- End Rem
- Function OnKeyDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKPanel(obj).style & PANEL_ACTIVE Then
- Local _key:Int, _mods:Int
- bmx_gtk3maxgui_gdkeventkey(event, Varptr _key, Varptr _mods)
- Local key:Int = TGTKKeyMap.mapBack(_key)
- Local mods:Int = TGTKKeyMap.mapModifierBack(_mods)
-
- If Not gtk3SetKeyDown(key) Then
- PostGuiEvent(EVENT_KEYDOWN, TGadget(obj), key, mods)
- Else
- PostGuiEvent(EVENT_KEYREPEAT, TGadget(obj), key, mods)
- End If
- Local char:Int = gdk_keyval_to_unicode(_key)
- ' we sometimes get 0 from this function when key is valid... so set it to key just so that it has a value.
- If char = 0 And key <> 0 Then
- char = key
- End If
- PostGuiEvent(EVENT_KEYCHAR, TGadget(obj), char, mods)
-
- Return True
- End If
- End Function
- Rem
- bbdoc: Callback for key up
- End Rem
- Function OnKeyUp:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- If TGTKPanel(obj).style & PANEL_ACTIVE Then
- Local _key:Int, _mods:Int
- bmx_gtk3maxgui_gdkeventkey(event, Varptr _key, Varptr _mods)
- Local key:Int = TGTKKeyMap.mapBack(_key)
- Local mods:Int = TGTKKeyMap.mapModifierBack(_mods)
-
- gtk3SetKeyUp(key)
- PostGuiEvent(EVENT_KEYUP, TGadget(obj), key, mods)
-
- Return True
- End If
- End Function
- Rem
- bbdoc: Sets the text of a group panel.
- End Rem
- Method SetText:Int(text:String)
- If style & PANEL_GROUP Then
- If text = Null Or text.length = 0 Then
- gtk_frame_set_label(frame, Null)
- Else
- Local textPtr:Byte Ptr = text.ToUTF8String()
- gtk_frame_set_label(frame, textPtr)
- MemFree(textPtr)
- End If
- End If
- End Method
- Rem
- bbdoc: Shows or hides a panel
- End Rem
- Method SetShow:Int(truefalse:Int)
- visible = truefalse
- mySetVisible = visible
-
- If truefalse Then
- If frame Then
- gtk_widget_show(frame)
- Else
- gtk_widget_show(handle)
- End If
- Else
- If frame Then
- gtk_widget_hide(frame)
- Else
- gtk_widget_hide(handle)
- End If
- EndIf
- UpdateChildVisibility()
- End Method
- Method free:Int() Override
- Super.Free()
- If frame Then
- gtk_widget_destroy(frame)
- Else
- If handle Then
- gtk_widget_destroy(handle)
- End If
- End If
-
- container = Null
- handle = Null
- frame = Null
-
- If panelpixmap Then
- panelpixmap = Null
- End If
- If panelPixbuf Then
- g_object_unref(panelPixbuf)
- panelPixbuf = Null
- End If
- End Method
- Rem
- bbdoc: Set the panel color.
- End Rem
- Method SetColor:Int(r:Int, g:Int, b:Int)
- Local color:GdkRGBA = New GdkRGBA(r / 255.0, g / 255.0, b / 255.0)
- gtk_widget_override_background_color(handle, GTK_STATE_FLAG_NORMAL, color)
- End Method
- Rem
- bbdoc: Set the panel pixmap.
- End Rem
- Method SetPixmap:Int(pixmap:TPixmap, flags:Int)
- pixmapMode = flags
-
- If pixmap Then
- If PixmapFormat(pixmap) <> PF_RGBA8888 And PixmapFormat(pixmap) <> PF_BGRA8888 Then
- panelPixmap = pixmap.convert( PF_RGBA8888 )
- Else
- panelPixmap = pixmap
- End If
-
- If panelPixbuf Then
- g_object_unref(panelPixbuf)
- End If
- panelPixbuf = gdk_pixbuf_new_from_data(panelPixmap.pixels, GDK_COLORSPACE_RGB, True, 8, ..
- panelPixmap.width, panelPixmap.height, panelPixmap.Pitch, Null, Null)
- Else
- If panelPixmap Then
- panelPixmap = Null
- End If
- End If
- redraw()
- End Method
-
- Method rethink:Int()
- If frame Then
- gtk_layout_move(TGTKContainer(parent).container, frame, xpos, ypos)
- gtk_widget_set_size_request(frame, Max(width,0), Max(height,0))
- Else If handle Then
- gtk_layout_move(TGTKContainer(parent).container, handle, xpos, ypos)
- gtk_widget_set_size_request(handle, Max(width,0), Max(height,0))
- End If
- redraw()
- End Method
- Method redraw()
- If Not panelPixmap Then
- If panelPixbuf Then
- g_object_unref(panelPixbuf)
- panelPixbuf = Null
- End If
- If visualpixbuf Then
- g_object_unref(visualpixbuf)
- visualpixbuf = Null
- ' make the panel redraw itself
- gtk_widget_queue_draw(handle)
- End If
- End If
-
- If panelPixbuf Then
-
- If visualpixbuf Then
- g_object_unref(visualpixbuf)
- End If
- Select pixmapMode & (PANELPIXMAP_TILE | PANELPIXMAP_CENTER | PANELPIXMAP_FIT | PANELPIXMAP_FIT2 | PANELPIXMAP_STRETCH)
- Case PANELPIXMAP_TILE
- pbx = 0
- pby = 0
- Local w:Float = width
- Local h:Float = height
- Local wfull:Int = w / panelPixmap.width
- Local hfull:Int = h / panelPixmap.height
-
- Local wpart:Int = w Mod panelPixmap.width
- Local hpart:Int = h Mod panelPixmap.height
-
- visualpixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, True, 8, Int(w), Int(h))
-
- For Local x:Int = 0 Until wfull
-
- For Local y:Int = 0 Until hfull
- gdk_pixbuf_copy_area(panelPixbuf, 0, 0, panelPixmap.width, panelPixmap.height, visualpixbuf, x * panelPixmap.width, y * panelPixmap.height)
- Next
-
- If hpart > 0 Then
- gdk_pixbuf_copy_area(panelPixbuf, 0, 0, panelPixmap.width, hpart, visualpixbuf, x * panelPixmap.width, hfull * panelPixmap.height)
- End If
-
- Next
-
- If wpart > 0 Then
-
- For Local y:Int = 0 Until hfull
- gdk_pixbuf_copy_area(panelPixbuf, 0, 0, wpart, panelPixmap.height, visualpixbuf, wfull * panelPixmap.width, y * panelPixmap.height)
- Next
-
- If hpart > 0 Then
- gdk_pixbuf_copy_area(panelPixbuf, 0, 0, wpart, hpart, visualpixbuf, wfull * panelPixmap.width, hfull * panelPixmap.height)
- End If
-
- End If
-
- Case PANELPIXMAP_CENTER
- visualpixbuf = gdk_pixbuf_copy(panelPixBuf)
- pbx = width / 2 - panelPixmap.width / 2
- pby = height / 2 - panelPixmap.height / 2
-
- Case PANELPIXMAP_FIT
- Local _w:Float = width / (panelPixmap.width * 1.0)
- Local _h:Float = height / (panelPixmap.height * 1.0)
- Local newWidth:Int = Min(_w, _h) * panelPixmap.width
- Local newHeight:Int = Min(_w, _h) * panelPixmap.height
- pbx = width / 2 - newWidth / 2
- pby = height / 2 - newHeight / 2
- visualpixbuf = gdk_pixbuf_scale_simple(panelPixbuf, newWidth, newHeight, GDK_INTERP_BILINEAR)
- Case PANELPIXMAP_FIT2
- Local _w:Float = width / (panelPixmap.width * 1.0)
- Local _h:Float = height / (panelPixmap.height * 1.0)
- Local newWidth:Int = Max(_w, _h) * panelPixmap.width
- Local newHeight:Int = Max(_w, _h) * panelPixmap.height
- pbx = width / 2 - newWidth / 2
- pby = height / 2 - newHeight / 2
- visualpixbuf = gdk_pixbuf_scale_simple(panelPixbuf, newWidth, newHeight, GDK_INTERP_BILINEAR)
-
- Case PANELPIXMAP_STRETCH
- pbx = 0
- pby = 0
- visualpixbuf = gdk_pixbuf_scale_simple(panelPixbuf, width, height, GDK_INTERP_BILINEAR)
- End Select
-
- If Not drawPixbuf Then
- drawPixbuf = True
- End If
-
- End If
-
- ' make sure the panel refreshes visually
- Super.redraw()
- End Method
- Method Activate:Int(cmd:Int)
- Select cmd
- Case ACTIVATE_REDRAW
- redraw()
- Default
- Super.Activate(cmd)
- End Select
- End Method
- Method toString:String()
- Return "TGTKPanel"
- End Method
- End Type
- Rem
- bbdoc: A canvas.
- End Rem
- Type TGTKCanvas Extends TGTKGadget
- Field canvas:TGraphics
- Field Mode:Long
-
- Function CreateCanvas:TGTKCanvas(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKCanvas = New TGTKCanvas
- this.initCanvas(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initCanvas(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- handle = gtk_drawing_area_new()
- Init(GTK_CANVAS, x, y, w, h, style)
- gtk_layout_put(TGTKContainer(group).container, handle, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- sensitivity:| SENSITIZE_MOUSE | SENSITIZE_KEYS
- ' we need to allow the drawing area to accept focus !
- g_object_set_int(handle, "can-focus", True)
- ' we need to handle our own redrawing...
- 'gtk_widget_set_double_buffered(handle, False)
- addConnection("draw", g_signal_cb3(handle, "draw", CanvasRedraw, Self, Destroy, 0))
- gtk_widget_add_events(handle, GDK_BUTTON_PRESS_MASK | ..
- GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | ..
- GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK)' | ..
- ' GDK_POINTER_MOTION_HINT_MASK)
- addConnection("button-press-event", g_signal_cb3_ret(handle, "button-press-event", OnMouseDown, Self, Destroy, 0))
- addConnection("button-release-event", g_signal_cb3_ret(handle, "button-release-event", OnMouseUp, Self, Destroy, 0))
- addConnection("enter-notify-event", g_signal_cb3_ret(handle, "enter-notify-event", OnMouseEnter, Self, Destroy, 0))
- addConnection("leave-notify-event", g_signal_cb3_ret(handle, "leave-notify-event", OnMouseLeave, Self, Destroy, 0))
- addConnection("motion-notify-event", g_signal_cb3_ret(handle, "motion-notify-event", OnMouseMove, Self, Destroy, 0))
- addConnection("scroll-event", g_signal_cb3(handle, "scroll-event", OnScroll, Self, Destroy, 0))
- addConnection("key-press-event", g_signal_cb3_ret(handle, "key-press-event", OnKeyDown, Self, Destroy, 0))
- addConnection("key-release-event", g_signal_cb3_ret(handle, "key-release-event", OnKeyUp, Self, Destroy, 0))
- SetShow(True)
- End Method
- Function CanvasRedraw(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- PostGuiEvent(EVENT_GADGETPAINT, TGadget(obj))
- End Function
-
- Method AttachGraphics:TGraphics( flags:Long )
- Mode = flags
- End Method
- Method CanvasGraphics:TGraphics()
- If Not canvas Then
- canvas = BRL.Graphics.AttachGraphics(gdk_x11_window_get_xid(gtk_widget_get_window(handle)), Mode)
- End If
- Return canvas
- End Method
- Method Activate:Int(cmd:Int)
- If cmd <> ACTIVATE_REDRAW Then
- Super.Activate(cmd)
- End If
- Select cmd
- Case ACTIVATE_REDRAW
- gtk_widget_queue_draw(handle)
- End Select
- End Method
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then
- button = 2
- Else If button = 2 Then
- button = 3
- End If
- PostGuiEvent(EVENT_MOUSEDOWN, TGadget(obj),button,,Int(x),Int(y))
- Return True
- End Function
-
- Function OnScroll(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, direction:Int
- bmx_gtk3maxgui_gdkeventscroll(event, Varptr x, Varptr y, Varptr direction)
- If direction = GDK_SCROLL_UP Or direction = GDK_SCROLL_LEFT Then
- PostGuiEvent(EVENT_MOUSEWHEEL, TGadget(obj),-1,,Int(x),Int(y))
- Else
- PostGuiEvent(EVENT_MOUSEWHEEL, TGadget(obj),1,,Int(x),Int(y))
- End If
- End Function
- Function OnMouseUp:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then
- button = 2
- Else If button = 2 Then
- button = 3
- End If
- PostGuiEvent(EVENT_MOUSEUP, TGadget(obj),button,,Int(x),Int(y))
- Return True
- End Function
- Function OnMouseEnter:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- PostGuiEvent(EVENT_MOUSEENTER, TGadget(obj))
- Return True
- End Function
- Function OnMouseLeave:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- PostGuiEvent(EVENT_MOUSELEAVE, TGadget(obj))
- Return True
- End Function
- 'Rem
- 'bbdoc: Callback for mouse movement
- 'End Rem
- Function OnMouseMove:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventmotion(event, Varptr x, Varptr y, Varptr button)
- If button & GDK_BUTTON1_MASK Then
- button = 1
- Else If button & GDK_BUTTON3_MASK Then
- button = 2
- Else If button & GDK_BUTTON2_MASK Then
- button = 3
- Else
- button = 0
- End If
- PostGuiEvent(EVENT_MOUSEMOVE, TGadget(obj),button,,Int(x),Int(y))
- Return True
- End Function
- Function OnKeyDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local _key:Int, _mods:Int
- bmx_gtk3maxgui_gdkeventkey(event, Varptr _key, Varptr _mods)
- Local key:Int = TGTKKeyMap.mapBack(_key)
- Local mods:Int = TGTKKeyMap.mapModifierBack(_mods)
- If Not gtk3SetKeyDown(key) Then
- PostGuiEvent(EVENT_KEYDOWN, TGadget(obj), key, mods)
- Else
- PostGuiEvent(EVENT_KEYREPEAT, TGadget(obj), key, mods)
- End If
- Local char:Int = gdk_keyval_to_unicode(_key)
- ' we sometimes get 0 from this function when key is valid... so set it to key just so that it has a value.
- If char = 0 And key <> 0 Then
- char = key
- End If
- PostGuiEvent(EVENT_KEYCHAR, TGadget(obj), char, mods)
- Return True
- End Function
- Function OnKeyUp:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local _key:Int, _mods:Int
- bmx_gtk3maxgui_gdkeventkey(event, Varptr _key, Varptr _mods)
- Local key:Int = TGTKKeyMap.mapBack(_key)
- Local mods:Int = TGTKKeyMap.mapModifierBack(_mods)
-
- gtk3SetKeyUp(key)
- PostGuiEvent(EVENT_KEYUP, TGadget(obj), key, mods)
- Return True
- End Function
- Method free:Int()
- Super.free()
-
- If canvas
- canvas.Close()
- canvas = Null
- End If
-
- If handle
- gtk_widget_destroy(handle)
- EndIf
- handle = Null
- End Method
- End Type
- Rem
- bbdoc: A text area.
- End Rem
- Type TGTKDefaultTextArea Extends TGTKTextArea
- Field _tabsize:Int = 4
- Field scrollWindow:Byte Ptr
- Field _textBuffer:Byte Ptr
- Field _textTagTable:Byte Ptr
- Field _tabArray:Byte Ptr
- Field ignoreChange:Int
- Field fastUpdate:Int = False
-
- 'Field _selStart:Int
- 'Field _selEnd:Int
- Function CreateTextArea:TGTKTextArea(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Local this:TGTKDefaultTextArea = New TGTKDefaultTextArea
- this.initTextArea(x, y, w, h, label, group, style)
- Return this
- End Function
- Method initTextArea(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- _textBuffer = gtk_text_buffer_new(Null)
- _textTagTable = gtk_text_buffer_get_tag_table(_textBuffer)
- handle = gtk_text_view_new_with_buffer(_textBuffer)
- gtk_widget_show(handle)
-
- ' we need these events to allow tooltips to work
- gtk_widget_add_events(handle, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK)
- ' use word-wrapping ?
- If style & TEXTAREA_WORDWRAP Then
- gtk_text_view_set_wrap_mode(handle, GTK_WRAP_WORD_CHAR)
- End If
- ' a read-only textarea ?
- If style & TEXTAREA_READONLY Then
- gtk_text_view_set_editable(handle, False)
- End If
- Init(GTK_TEXTFIELD, x, y, w, h, style)
- ' scrollbars for the textarea...
- scrollWindow = gtk_scrolled_window_new(Null, Null)
- ' set container resize mode
- gtk_container_set_resize_mode(scrollWindow, GTK_RESIZE_QUEUE)
- ' set scrollbar policy
- gtk_scrolled_window_set_policy(scrollWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC)
- ' show
- gtk_widget_show(scrollWindow)
- ' add the text area to the scroll window
- gtk_container_add(scrollWindow, handle)
- addConnection("changed", g_signal_cb2(_textBuffer, "changed", OnTextChanged, Self, Destroy, 0))
- addConnection("move-cursor", g_signal_cb5(handle, "move-cursor", OnCursorMoved, Self, Destroy, 0))
- addConnection("button-press-event", g_signal_cb3_ret(handle, "button-press-event", OnMouseDown, Self, Destroy, 0))
- addConnection("button-release-event", g_signal_cb3_ret(handle, "button-release-event", OnMouseUp, Self, Destroy, 0))
- addConnection("key-press-event", g_signal_cb3_ret(handle, "key-press-event", OnKeyDown, Self, Destroy, 0))
- addConnection("focus-out-event", g_signal_cb3_ret(handle, "focus-out-event", OnFocusLost, Self, Destroy, 0))
- 'g_signal_cb3(handle, "visibility-notify-event", OnVisibilityChange, Self, Destroy, 0)
- gtk_layout_put(TGTKContainer(group).container, scrollwindow, x, y)
- gtk_widget_set_size_request(handle, w, Max(h,0))
- End Method
- Rem
- bbdoc: Callback for text change
- End Rem
- Function OnTextChanged(widget:Byte Ptr, obj:Object)
- If Not TGTKDefaultTextArea(obj).ignoreChange Then
- PostGuiEvent(EVENT_GADGETSELECT, TGadget(obj))
- PostGuiEvent(EVENT_GADGETACTION, TGadget(obj))
- End If
- TGTKDefaultTextArea(obj).ignoreChange = False
- End Function
- Rem
- bbdoc: Callback for text-cursor movement
- End Rem
- Function OnCursorMoved(widget:Byte Ptr, _Step:Int, count:Int, extend_selection:Int, obj:Object)
- PostGuiEvent(EVENT_GADGETSELECT, TGadget(obj))
- End Function
- Rem
- bbdoc: Callback for mouse button press
- End Rem
- Function OnMouseDown:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then ' right mouse button
- ' ignore this... see MouseUp for menu event!
- Return True
- End If
- PostGuiEvent(EVENT_GADGETSELECT, TGadget(obj))
- End Function
- Rem
- bbdoc: Callback for mouse button release
- End Rem
- Function OnMouseUp:Int(widget:Byte Ptr, event:Byte Ptr, obj:Object)
- Local x:Double, y:Double, button:Int
- bmx_gtk3maxgui_gdkeventbutton(event, Varptr x, Varptr y, Varptr button)
- If button = 3 Then ' right mouse button
- PostGuiEvent(EVENT_GADGETMENU, TGadget(obj),,,Int(x),Int(y))
- Return True
- End If
- PostGuiEvent(EVENT_GADGETSELECT, TGadget(obj))
- End Function
-
- Rem
- bbdoc: Adds text to the end of the text.
- End Rem
- Method AddText:Int(text:String)
- Local _end:Byte Ptr = bmx_gtk3_gtktextiter_new()
- ' get the end of the text
- gtk_text_buffer_get_end_iter(_textBuffer, _end)
- ignoreChange = True
- Local textPtr:Byte Ptr = text.ToUTF8String()
- gtk_text_buffer_insert(_textBuffer, _end, textPtr, -1)
- MemFree(textPtr)
- gtk_text_buffer_get_end_iter(_textBuffer, _end)
- ?bmxng
- IWrappedSystemDriver(SystemDriver()).GetDriver().Poll()
- ?Not bmxng
- brl.System.Driver.Poll() ' update events, before scrolling to the end...
- ?
- gtk_text_view_scroll_to_iter(handle, _end, 0, False, 0, 0)
-
- bmx_gtk3_gtktextiter_free(_end)
- End Method
- Rem
- bbdoc: Returns the text For the specified location
- End Rem
- Method AreaText:String(pos:Int, length:Int, units:Int)
- Local _start:Byte Ptr = bmx_gtk3_gtktextiter_new()
- Local _end:Byte Ptr = bmx_gtk3_gtktextiter_new()
- If units = TEXTAREA_LINES Then
- gtk_text_buffer_get_iter_at_line(_textBuffer, _start, pos)
- gtk_text_buffer_get_iter_at_line(_textBuffer, _end, pos + length)
- Else ' must be TEXTAREA_CHARS
- gtk_text_buffer_get_iter_at_offset(_textBuffer, _start, pos)
- gtk_text_buffer_get_iter_at_offset(_textBuffer, _end, pos + length)
- End If
- Local s:Byte Ptr = gtk_text_buffer_get_text(_textBuffer, _start, _end, False)
- Local st:String = String.FromUTF8String(s)
- g_free(s)
-
- bmx_gtk3_gtktextiter_free(_start)
- bmx_gtk3_gtktextiter_free(_end)
-
- Return st
- End Method
- Rem
- bbdoc: Returns either the number of characters or number of rows.
- End Rem
- Method AreaLen:Int(units:Int)
- If units = TEXTAREA_LINES Then
- Return gtk_text_buffer_get_line_count(_textBuffer)
- Else
- Return gtk_text_buffer_get_char_count(_textBuffer)
- End If
- End Method
- Rem
- bbdoc: Returns the current cursor position value, in characters or lines
- End Rem
- Method GetCursorPos:Int(units:Int)
- Local pos:Int = 0
- Local _start:Byte Ptr = bmx_gtk3_gtktextiter_new()
- Local _end:Byte Ptr = bmx_gtk3_gtktextiter_new()
- ' Since the cursor position might be at the end of selected text, we get the selection
- ' bounds and get the *start* location. If there is no selection, start and end will be the same
- gtk_text_buffer_get_selection_bounds(_textBuffer, _start, _end)
-
- If units = TEXTAREA_LINES Then
- pos = gtk_text_iter_get_line(_start)
- Else ' must be TEXTAREA_CHARS
- pos = gtk_text_iter_get_offset(_start)
- End If
- bmx_gtk3_gtktextiter_free(_start)
- bmx_gtk3_gtktextiter_free(_end)
- Return pos
- End Method
- Rem
- bbdoc: Set the text area visibility.
- End Rem
- Method SetShow:Int(truefalse:Int)
- visible = truefalse
- mySetVisible = visible
-
- If truefalse Then
- gtk_widget_show(handle)
- gtk_widget_show(scrollWindow)
- Else
- gtk_widget_hide(scrollWindow)
- EndIf
- End Method
- Rem
- bbdoc: Set the text area font.
- End Rem
- Method SetFont:Int(font:TGuiFont)
- Super.SetFont(font)
- ' we need to reset the tabs, as it is lost when font is changed.
- SetTabs(_tabsize)
- End Method
- Rem
- bbdoc: Sets the text buffer text
- End Rem
- Method SetText:Int(text:String)
- ignoreChange = True
- Local textPtr:Byte Ptr = text.ToUTF8String()
- gtk_text_buffer_set_text(_textBuffer, textPtr, -1)
- MemFree(textPtr)
- ' move the cursor to the start
- Local _start:Byte Ptr = bmx_gtk3_gtktextiter_new()
- gtk_text_buffer_get_iter_at_line(_textBuffer, _start, 0)
- gtk_text_buffer_place_cursor(_textBuffer, _start)
- gtk_text_view_scroll_mark_onscreen(handle, gtk_text_buffer_get_insert(_textBuffer))', 0, False, 0, 0.1)
-
- bmx_gtk3_gtktextiter_free(_start)
- End Method
- Rem
- bbdoc: Set the text area selection
- End Rem
- Method SetSelection:Int(pos:Int, length:Int, units:Int)
- Local _start:Byte Ptr = bmx_gtk3_gtktextiter_new()
- Local _end:Byte Ptr = bmx_gtk3_gtktextiter_new()
- If units = TEXTAREA_LINES Then
- gtk_text_buffer_get_iter_at_line(_textBuffer, _start, pos)
- gtk_text_buffer_get_iter_at_line(_textBuffer, _end, pos + length)
- Else ' must be TEXTAREA_CHARS
- gtk_text_buffer_get_iter_at_offset(_textBuffer, _start, pos)
- gtk_text_buffer_get_iter_at_offset(_textBuffer, _end, pos + length)
- End If
- gtk_text_buffer_place_cursor(_textBuffer, _start)
- gtk_text_view_scroll_mark_onscreen(handle, gtk_text_buffer_get_insert(_textBuffer))
-
- gtk_text_buffer_select_range(_textBuffer, _start, _end)
- PostGuiEvent(EVENT_GADGETSELECT, Self)
- ' scroll to the start of the selection
- ' NOTE: setting param4 to False causes it to scroll only as much as required to show the start
- ' Set to True to cause it to always display at the same point on the visible area.
- gtk_text_view_scroll_to_iter(handle, _start, 0, False, 0, 0.1)
- bmx_gtk3_gtktextiter_free(_start)
- bmx_gtk3_gtktextiter_free(_end)
- End Method
- Rem
- bbdoc: Returns the size of the current selection, in characters or lines.
- End Rem
- Method GetSelectionLength:Int(units:Int)
- Local length:Int = 0
- Local _start:Byte Ptr = bmx_gtk3_gtktextiter_new()
- Local _end:Byte Ptr = bmx_gtk3_gtktextiter_new()
- Local hasSelection:Int = gtk_text_buffer_get_selection_bounds(_textBuffer, _start, _end)
- If hasSelection Then
- If units = TEXTAREA_LINES Then
-
- gtk_text_iter_backward_char(_end)
- length = (gtk_text_iter_get_line(_end) - gtk_text_iter_get_line(_start)) + 1
- Else ' must be TEXTAREA_CHARS
- length = gtk_text_iter_get_offset(_end) - gtk_text_iter_get_offset(_start)
- End If
- End If
- bmx_gtk3_gtktextiter_free(_start)
- bmx_gtk3_gtktextiter_free(_end)
- Return length
- End Method
- Rem
- bbdoc: Sets the style of part of the text area
- about: @flags are any mix of TEXTFORMAT_BOLD, TEXTFORMAT_ITALIC, TEXTFORMAT_UNDERLINE and TEXTFORMAT_STRIKETHROUGH.<br/>
- We utilise the buffers' tag table to cache tags that we reuse - based on the attributes.
- This way we only create one for each different style we actually use in the buffer.<br/>
- Note: "fastUpdate" flag enables or disables the use of gtk_text_buffer_remove_all_tags which strips
- old tags from the area before applying the new one.<br/>
- Ideally, you would first remove tags before applying new ones, but since removal is slow, the following
- method can work well :
- <pre>
- setFastUpdate(false)
- SetStyle on whole intended area to "normal" style
- setFastUpdate(true)
- iterate thru tokens applying styles..
- </pre>
- End Rem
- Method SetStyle:Int(r:Int, g:Int, b:Int, flags:Int, pos:Int, length:Int, units:Int)
- ' Build a style string
- Local s:Int = r Shl 24 | g Shl 16 | b Shl 8 | (flags & $ff)
- Local styleText:String = String(s)
- ' Does this one already exist?
- Local _textTag:Byte Ptr = gtk_text_tag_table_lookup(_textTagTable, styleText)
- ' nope... so we need to create it
- If _textTag = Null Then
- Local color:GdkRGBA = New GdkRGBA(r / 255.0, g / 255.0, b / 255.0)
- '
- Local _style:Int = PANGO_STYLE_NORMAL
- If flags & TEXTFORMAT_ITALIC Then
- _style = PANGO_STYLE_ITALIC
- End If
- Local _weight:Int = PANGO_WEIGHT_NORMAL
- If flags & TEXTFORMAT_BOLD Then
- _weight = PANGO_WEIGHT_BOLD
- End If
- Local _under:Int = PANGO_UNDERLINE_NONE
- If flags & TEXTFORMAT_UNDERLINE Then
- _under = PANGO_UNDERLINE_SINGLE
- End If
- Local _strike:Int = False
- If flags & TEXTFORMAT_STRIKETHROUGH Then
- _strike = True
- End If
- ' create and setup the tag
- _textTag = bmx_gtk3_set_text_tag_style(_textBuffer, styleText, color, _style, _weight, _under, _strike)
-
- End If
- applyStyle(pos, length, units, _textTag)
-
- End Method
-
- Method applyStyle(pos:Int, length:Int, units:Int, _textTag:Byte Ptr)
- ' set up start and end points
- Local _start:Byte Ptr = bmx_gtk3_gtktextiter_new()
- Local _end:Byte Ptr = bmx_gtk3_gtktextiter_new()
- If units = TEXTAREA_LINES Then
- gtk_text_buffer_get_iter_at_line(_textBuffer, _start, pos)
- gtk_text_buffer_get_iter_at_line(_textBuffer, _end, pos + length)
- Else ' must be TEXTAREA_CHARS
- gtk_text_buffer_get_iter_at_offset(_textBuffer, _start, pos)
- gtk_text_buffer_get_iter_at_offset(_textBuffer, _end, pos + length)
- End If
- ' remove any existing tags in the range first - otherwise they'll just pile up
- ' NOTE : except that this is REALLY slow....
- If Not fastUpdate Then
- gtk_text_buffer_remove_all_tags(_textBuffer, _start, _end)
- End If
- ' apply the tag to the range
- gtk_text_buffer_apply_tag(_textBuffer, _textTag, _start, _end)
-
- bmx_gtk3_gtktextiter_free(_start)
- bmx_gtk3_gtktextiter_free(_end)
- End Method
- Method SetBGStyle(r:Int, g:Int, b:Int, pos:Int, length:Int, units:Int)
- ' Build a style string
- Local styleText:String = r + "_" + g + "_" + b + "_bg"
- ' Does this one already exist?
- Local _textTag:Byte Ptr = gtk_text_tag_table_lookup(_textTagTable, styleText)
- ' nope... so we need to create it
- If _textTag = Null Then
- Local color:GdkRGBA = New GdkRGBA(r / 255.0, g / 255.0, b / 255.0)
-
- ' create and setup the tag
- _textTag = bmx_gtk3_set_text_bg_tag(_textBuffer, styleText, color)
- End If
- applyStyle(pos, length, units, _textTag)
- End Method
- Method ReplaceText:Int(pos:Int, length:Int, text:String, units:Int)
- If length = TEXTAREA_ALL Then
- SetText(text)
- Else
- ' set up start and end points
- Local _start:Byte Ptr = bmx_gtk3_gtktextiter_new()
- Local _end:Byte Ptr = bmx_gtk3_gtktextiter_new()
-
- If units = TEXTAREA_LINES Then
- gtk_text_buffer_get_iter_at_line(_textBuffer, _start, pos)
- gtk_text_buffer_get_iter_at_line(_textBuffer, _end, pos + length)
- Else ' must be TEXTAREA_CHARS
- gtk_text_buffer_get_iter_at_offset(_textBuffer, _start, pos)
- gtk_text_buffer_get_iter_at_offset(_textBuffer, _end, pos + length)
- End If
-
- ' remove the specified range
- gtk_text_buffer_delete(_textBuffer, _start, _end)
-
- ' insert new text
- Local textPtr:Byte Ptr = text.ToUTF8String()
- gtk_text_buffer_insert(_textBuffer, _start, textPtr, -1)
- MemFree(textPtr)
-
- bmx_gtk3_gtktextiter_free(_start)
- bmx_gtk3_gtktextiter_free(_end)
- End If
- End Method
- Rem
- bbdoc: Locks the text area.
- End Rem
- Method LockText:Int()
- gtk_text_view_set_editable(handle, False)
- End Method
- Rem
- bbdoc: Unlocks the text area
- End Rem
- Method UnlockText:Int()
- gtk_text_view_set_editable(handle, True)
- End Method
- Rem
- bbdoc:
- End Rem
- Method SetTabs:Int(tabs:Int)
- ' cache the current size
- _tabsize = tabs
- ' get the current tab array - returns Null if default 8-space setting
- _tabArray = gtk_text_view_get_tabs(handle)
-
- If _tabArray <> Null Then
- pango_tab_array_free(_tabArray)
- End If
- Local tabmul:Int = 8 * 1024
- If _font <> Null Then
- tabmul = _font.size * 1024
- End If
- _tabArray = pango_tab_array_new_with_positions(1, False, PANGO_TAB_LEFT, tabs * tabmul)
- gtk_text_view_set_tabs(handle, _tabArray)
- End Method
- Method CharAt:Int(line:Int)
- Local _iter:Byte Ptr = bmx_gtk3_gtktextiter_new()
- gtk_text_buffer_get_iter_at_line(_textBuffer, _iter, line)
- Local ret:Int = gtk_text_iter_get_offset(_iter)
- bmx_gtk3_gtktextiter_free(_iter)
- Return ret
- End Method
- Method LineAt:Int(index:Int)
- Local _iter:Byte Ptr = bmx_gtk3_gtktextiter_new()
- gtk_text_buffer_get_iter_at_offset(_textBuffer, _iter, index)
- Local ret:Int = gtk_text_iter_get_line(_iter)
- bmx_gtk3_gtktextiter_free(_iter)
- Return ret
- End Method
- Method free:Int() Override
- Super.Free()
- If scrollWindow Then
- gtk_widget_destroy(scrollWindow)
- EndIf
- handle = Null
- scrollWindow = Null
- End Method
- Method Activate:Int(cmd:Int)
- Super.Activate(cmd)
- Select cmd
- Case ACTIVATE_CUT
- Local clipboard:Byte Ptr = gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", True))
- gtk_text_buffer_cut_clipboard(_textBuffer, clipboard, True)
- Case ACTIVATE_COPY
- Local clipboard:Byte Ptr = gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", True))
- gtk_text_buffer_copy_clipboard(_textBuffer, clipboard)
- Case ACTIVATE_PASTE
- Local clipboard:Byte Ptr = gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", True))
- gtk_text_buffer_paste_clipboard(_textBuffer, clipboard, Null, True)
- End Select
- End Method
-
- Rem
- bbdoc: Enable to allow *fast* formatting.
- about: When enabled, highlighting will not be removed before being applied, and since
- tags are ordered, some highlight may not appear on top of others.
- End Rem
- Method setFastUpdate(bool:Int)
- fastUpdate = bool
- End Method
-
- Method Rethink:Int()
- If handle Then
- gtk_layout_move(TGTKContainer(parent).container, scrollWindow, Max(xpos, 0), Max(ypos, 0))
- gtk_widget_set_size_request(scrollWindow, Max(width,0), Max(height,0))
- End If
- End Method
- End Type
- Rem
- bbdoc: A base type for html view gadgets.
- about: Implementations are in seperate modules.<br/>
- See bah.gtkwebmozilla and bah.gtkwebgtkhtml mods.
- End Rem
- Type TGTKHTMLView Extends TGTKGadget
- Function CreateHTMLView:TGTKHTMLView(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int) Abstract
-
- Method Stop() Abstract
- Method SetText:Int(url:String) Abstract
- Method GetText:String() Abstract
- End Type
- Type TGTKWebDriver
- Function CreateHTMLView:TGTKHTMLView(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int) Abstract
- End Type
- Global gtk3maxgui_htmlview:TGTKWebDriver
- Rem
- bbdoc: A base type for text area gadgets.
- about: Implementations are in seperate modules, except for the default TGTKDefaultTextArea
- End Rem
- Type TGTKTextArea Extends TGTKEditable
- Function CreateTextArea:TGTKTextArea(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int) Abstract
- End Type
- Type TGTKTextAreaDriver
- Function CreateTextArea:TGTKTextArea(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int) Abstract
- End Type
- ' default text area driver
- Type TGTKDefaultTextAreaDriver Extends TGTKTextAreaDriver
- Function CreateTextArea:TGTKTextArea(x:Int, y:Int, w:Int, h:Int, label:String, group:TGadget, style:Int)
- Return TGTKDefaultTextArea.CreateTextArea(x, y, w, h, label, group, style)
- End Function
- End Type
- Global gtk3maxgui_textarea:TGTKTextAreaDriver
- Extern
- Function g_object_get_menudata:TGTKMenuItem(handle:Byte Ptr, name:Byte Ptr) = "g_object_get_data"
- End Extern
|