psmap_dialogs.py 298 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409
  1. """!
  2. @package psmap_dialogs.py
  3. @brief Map feature objects and dialogs for ps.map
  4. Classes:
  5. - UnitConversion
  6. - TCValidator
  7. - PenStyleComboBox
  8. - CheckListCtrl
  9. - Instruction
  10. - InstructionObject
  11. - InitMap
  12. - MapFrame
  13. - PageSetup
  14. - Mapinfo
  15. - Text
  16. - Image
  17. - NorthArrow
  18. - Scalebar
  19. - RasterLegend
  20. - VectorLegend
  21. - Raster
  22. - Vector
  23. - VProperties
  24. - PsmapDialog
  25. - PageSetupDialog
  26. - MapDialog
  27. - MapFramePanel
  28. - RasterPanel
  29. - VectorPanel
  30. - RasterDialog
  31. - MainVectorDialog
  32. - VPropertiesDialog
  33. - LegendDialog
  34. - MapinfoDialog
  35. - ScalebarDialog
  36. - TextDialog
  37. - ImageDialog
  38. - NorthArrowDialog
  39. (C) 2011 by Anna Kratochvilova, and the GRASS Development Team
  40. This program is free software under the GNU General Public License
  41. (>=v2). Read the file COPYING that comes with GRASS for details.
  42. @author Anna Kratochvilova <kratochanna gmail.com> (bachelor's project)
  43. @author Martin Landa <landa.martin gmail.com> (mentor)
  44. """
  45. import os
  46. import sys
  47. import string
  48. from math import ceil, floor, sin, cos, pi
  49. from copy import deepcopy
  50. from time import strftime, localtime
  51. try:
  52. import Image as PILImage
  53. havePILImage = False
  54. except ImportError:
  55. havePILImage = False
  56. import grass.script as grass
  57. if int(grass.version()['version'].split('.')[0]) > 6:
  58. sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'gui', 'wxpython',
  59. 'gui_modules'))
  60. else:
  61. sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'wxpython',
  62. 'gui_modules'))
  63. import globalvar
  64. import dbm_base
  65. from utils import CmdToTuple, GetCmdString
  66. from gselect import Select
  67. from gcmd import RunCommand, GError, GMessage, GWarning
  68. import wx
  69. import wx.lib.scrolledpanel as scrolled
  70. import wx.lib.filebrowsebutton as filebrowse
  71. from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
  72. from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED
  73. try:
  74. import wx.lib.agw.floatspin as fs
  75. except ImportError:
  76. fs = None
  77. grass.set_raise_on_error(True)
  78. PSMAP_COLORS = ['aqua', 'black', 'blue', 'brown', 'cyan', 'gray', 'grey', 'green', 'indigo',
  79. 'magenta','orange', 'purple', 'red', 'violet', 'white', 'yellow']
  80. class UnitConversion:
  81. """! Class for converting units"""
  82. def __init__(self, parent = None):
  83. self.parent = parent
  84. if self.parent:
  85. ppi = wx.PaintDC(self.parent).GetPPI()
  86. else:
  87. ppi = (72, 72)
  88. self._unitsPage = { 'inch' : {'val': 1.0, 'tr' : _("inch")},
  89. 'point' : {'val': 72.0, 'tr' : _("point")},
  90. 'centimeter' : {'val': 2.54, 'tr' : _("centimeter")},
  91. 'millimeter' : {'val': 25.4, 'tr' : _("millimeter")}}
  92. self._unitsMap = { 'meters' : {'val': 0.0254, 'tr' : _("meters")},
  93. 'kilometers' : {'val': 2.54e-5, 'tr' : _("kilometers")},
  94. 'feet' : {'val': 1./12, 'tr' : _("feet")},
  95. 'miles' : {'val': 1./63360, 'tr' : _("miles")},
  96. 'nautical miles': {'val': 1/72913.386, 'tr' : _("nautical miles")}}
  97. self._units = { 'pixel' : {'val': ppi[0], 'tr' : _("pixel")},
  98. 'meter' : {'val': 0.0254, 'tr' : _("meter")},
  99. 'nautmiles' : {'val': 1/72913.386, 'tr' :_("nautical miles")},
  100. 'degrees' : {'val': 0.0254 , 'tr' : _("degree")} #like 1 meter, incorrect
  101. }
  102. self._units.update(self._unitsPage)
  103. self._units.update(self._unitsMap)
  104. def getPageUnitsNames(self):
  105. return sorted(self._unitsPage[unit]['tr'] for unit in self._unitsPage.keys())
  106. def getMapUnitsNames(self):
  107. return sorted(self._unitsMap[unit]['tr'] for unit in self._unitsMap.keys())
  108. def getAllUnits(self):
  109. return sorted(self._units.keys())
  110. def findUnit(self, name):
  111. """!Returns unit by its tr. string"""
  112. for unit in self._units.keys():
  113. if self._units[unit]['tr'] == name:
  114. return unit
  115. return None
  116. def findName(self, unit):
  117. """!Returns tr. string of a unit"""
  118. try:
  119. return self._units[unit]['tr']
  120. except KeyError:
  121. return None
  122. def convert(self, value, fromUnit = None, toUnit = None):
  123. return float(value)/self._units[fromUnit]['val']*self._units[toUnit]['val']
  124. class TCValidator(wx.PyValidator):
  125. """!validates input in textctrls, combobox, taken from wxpython demo"""
  126. def __init__(self, flag = None):
  127. wx.PyValidator.__init__(self)
  128. self.flag = flag
  129. self.Bind(wx.EVT_CHAR, self.OnChar)
  130. def Clone(self):
  131. return TCValidator(self.flag)
  132. def Validate(self, win):
  133. tc = self.GetWindow()
  134. val = tc.GetValue()
  135. if self.flag == 'DIGIT_ONLY':
  136. for x in val:
  137. if x not in string.digits:
  138. return False
  139. return True
  140. def OnChar(self, event):
  141. key = event.GetKeyCode()
  142. if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255:
  143. event.Skip()
  144. return
  145. if self.flag == 'DIGIT_ONLY' and chr(key) in string.digits + '.':
  146. event.Skip()
  147. return
  148. ## if self.flag == 'SCALE' and chr(key) in string.digits + ':':
  149. ## event.Skip()
  150. ## return
  151. if self.flag == 'ZERO_AND_ONE_ONLY' and chr(key) in '01':
  152. event.Skip()
  153. return
  154. if not wx.Validator_IsSilent():
  155. wx.Bell()
  156. # Returning without calling even.Skip eats the event before it
  157. # gets to the text control
  158. return
  159. class PenStyleComboBox(wx.combo.OwnerDrawnComboBox):
  160. """!Combo for selecting line style, taken from wxpython demo"""
  161. # Overridden from OwnerDrawnComboBox, called to draw each
  162. # item in the list
  163. def OnDrawItem(self, dc, rect, item, flags):
  164. if item == wx.NOT_FOUND:
  165. # painting the control, but there is no valid item selected yet
  166. return
  167. r = wx.Rect(*rect) # make a copy
  168. r.Deflate(3, 5)
  169. penStyle = wx.SOLID
  170. if item == 1:
  171. penStyle = wx.LONG_DASH
  172. elif item == 2:
  173. penStyle = wx.DOT
  174. elif item == 3:
  175. penStyle = wx.DOT_DASH
  176. pen = wx.Pen(dc.GetTextForeground(), 3, penStyle)
  177. dc.SetPen(pen)
  178. # for painting the items in the popup
  179. dc.DrawText(self.GetString(item ),
  180. r.x + 3,
  181. (r.y + 0) + ((r.height/2) - dc.GetCharHeight() )/2
  182. )
  183. dc.DrawLine(r.x+5, r.y+((r.height/4)*3)+1, r.x+r.width - 5, r.y+((r.height/4)*3)+1 )
  184. def OnDrawBackground(self, dc, rect, item, flags):
  185. """!Overridden from OwnerDrawnComboBox, called for drawing the
  186. background area of each item."""
  187. # If the item is selected, or its item # iseven, or we are painting the
  188. # combo control itself, then use the default rendering.
  189. if (item & 1 == 0 or flags & (wx.combo.ODCB_PAINTING_CONTROL |
  190. wx.combo.ODCB_PAINTING_SELECTED)):
  191. wx.combo.OwnerDrawnComboBox.OnDrawBackground(self, dc, rect, item, flags)
  192. return
  193. # Otherwise, draw every other background with different colour.
  194. bgCol = wx.Colour(240,240,250)
  195. dc.SetBrush(wx.Brush(bgCol))
  196. dc.SetPen(wx.Pen(bgCol))
  197. dc.DrawRectangleRect(rect);
  198. def OnMeasureItem(self, item):
  199. """!Overridden from OwnerDrawnComboBox, should return the height
  200. needed to display an item in the popup, or -1 for default"""
  201. return 30
  202. def OnMeasureItemWidth(self, item):
  203. """!Overridden from OwnerDrawnComboBox. Callback for item width, or
  204. -1 for default/undetermined"""
  205. return -1; # default - will be measured from text width
  206. class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
  207. """!List control for managing order and labels of vector maps in legend"""
  208. def __init__(self, parent):
  209. wx.ListCtrl.__init__(self, parent, id = wx.ID_ANY,
  210. style = wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.BORDER_SUNKEN|wx.LC_VRULES|wx.LC_HRULES)
  211. CheckListCtrlMixin.__init__(self)
  212. ListCtrlAutoWidthMixin.__init__(self)
  213. class Instruction:
  214. """!Class which represents instruction file"""
  215. def __init__(self, parent, objectsToDraw):
  216. self.parent = parent
  217. self.objectsToDraw = objectsToDraw
  218. #here are kept objects like mapinfo, rasterlegend, etc.
  219. self.instruction = list()
  220. def __str__(self):
  221. """!Returns text for instruction file"""
  222. comment = "# timestamp: " + strftime("%Y-%m-%d %H:%M", localtime()) + '\n'
  223. env = grass.gisenv()
  224. comment += "# location: %s\n" % env['LOCATION_NAME']
  225. comment += "# mapset: %s\n" % env['MAPSET']
  226. comment += "# page orientation: %s\n" % self.FindInstructionByType('page')['Orientation']
  227. border = ''
  228. if not self.FindInstructionByType('map'):
  229. border = 'border n\n'
  230. text = [str(each) for each in self.instruction]
  231. return comment + border + '\n'.join(text) + '\nend'
  232. def __getitem__(self, id):
  233. for each in self.instruction:
  234. if each.id == id:
  235. return each
  236. return None
  237. def __contains__(self, id):
  238. """!Test if instruction is included"""
  239. for each in self.instruction:
  240. if each.id == id:
  241. return True
  242. return False
  243. def __delitem__(self, id):
  244. """!Delete instruction"""
  245. for each in self.instruction:
  246. if each.id == id:
  247. if each.type == 'map':
  248. #must remove raster, vector layers too
  249. vektor = self.FindInstructionByType('vector', list = True)
  250. vProperties = self.FindInstructionByType('vProperties', list = True)
  251. raster = self.FindInstructionByType('raster', list = True)
  252. for item in vektor + vProperties + raster:
  253. if item in self.instruction:
  254. self.instruction.remove(item)
  255. self.instruction.remove(each)
  256. if id in self.objectsToDraw:
  257. self.objectsToDraw.remove(id)
  258. return
  259. def AddInstruction(self, instruction):
  260. """!Add instruction"""
  261. # add to instructions
  262. if instruction.type == 'map':
  263. self.instruction.insert(0, instruction)
  264. else:
  265. self.instruction.append(instruction)
  266. # add to drawable objects
  267. if instruction.type not in ('page', 'raster', 'vector', 'vProperties', 'initMap'):
  268. if instruction.type == 'map':
  269. self.objectsToDraw.insert(0, instruction.id)
  270. else:
  271. self.objectsToDraw.append(instruction.id)
  272. def FindInstructionByType(self, type, list = False):
  273. """!Find instruction(s) with the given type"""
  274. inst = []
  275. for each in self.instruction:
  276. if each.type == type:
  277. inst.append(each)
  278. if len(inst) == 1 and not list:
  279. return inst[0]
  280. return inst
  281. def Read(self, filename):
  282. """!Reads instruction file and creates instruction objects"""
  283. self.filename = filename
  284. # open file
  285. try:
  286. file = open(filename, 'r')
  287. except IOError:
  288. GError(message = _("Unable to open file\n%s") % filename)
  289. return
  290. # first read file to get information about region and scaletype
  291. isRegionComment = False
  292. orientation = 'Portrait'
  293. for line in file:
  294. if '# g.region' in line:
  295. self.SetRegion(regionInstruction = line)
  296. isRegionComment = True
  297. break
  298. if '# page orientation' in line:
  299. orientation = line.split(':')[-1].strip()
  300. if not isRegionComment:
  301. self.SetRegion(regionInstruction = None)
  302. # then run ps.map -b to get information for maploc
  303. # compute scale and center
  304. map = self.FindInstructionByType('map')
  305. region = grass.region()
  306. map['center'] = (region['n'] + region['s']) / 2, (region['w'] + region['e']) / 2
  307. mapRect = GetMapBounds(self.filename, portrait = (orientation == 'Portrait'))
  308. map['rect'] = mapRect
  309. proj = projInfo()
  310. toM = 1.0
  311. if proj['units']:
  312. toM = float(proj['meters'])
  313. units = UnitConversion(self.parent)
  314. w = units.convert(value = mapRect.Get()[2], fromUnit = 'inch', toUnit = 'meter') / toM
  315. map['scale'] = w / abs((region['w'] - region['e']))
  316. SetResolution(dpi = 300, width = map['rect'].width, height = map['rect'].height)
  317. # read file again, now with information about map bounds
  318. isBuffer = False
  319. buffer = []
  320. instruction = None
  321. vectorMapNumber = 1
  322. file.seek(0)
  323. for line in file:
  324. if not line.strip():
  325. continue
  326. line = line.strip()
  327. if isBuffer:
  328. buffer.append(line)
  329. if 'end' in line:
  330. isBuffer = False
  331. kwargs = {}
  332. if instruction == 'scalebar':
  333. kwargs['scale'] = map['scale']
  334. elif instruction in ('text', 'eps'):
  335. kwargs['mapInstruction'] = map
  336. elif instruction in ('vpoints', 'vlines', 'vareas'):
  337. kwargs['id'] = wx.NewId()
  338. kwargs['vectorMapNumber'] = vectorMapNumber
  339. vectorMapNumber += 1
  340. elif instruction == 'paper':
  341. kwargs['Orientation'] = orientation
  342. ok = self.SendToRead(instruction, buffer, **kwargs)
  343. if not ok: return False
  344. buffer = []
  345. continue
  346. elif line.startswith('paper'):
  347. instruction = 'paper'
  348. isBuffer = True
  349. buffer.append(line)
  350. elif line.startswith('border'):
  351. if line.split()[1].lower() in ('n', 'no', 'none'):
  352. ok = self.SendToRead('border', [line])
  353. if not ok: return False
  354. elif line.split()[1].lower() in ('y', 'yes'):
  355. instruction = 'border'
  356. isBuffer = True
  357. buffer.append(line)
  358. elif line.startswith('scale '):
  359. if isBuffer:
  360. continue
  361. ok = self.SendToRead('scale', line, isRegionComment = isRegionComment)
  362. if not ok: return False
  363. elif line.startswith('maploc'):
  364. ok = self.SendToRead(instruction = 'maploc', text = line)
  365. if not ok: return False
  366. elif line.startswith('raster'):
  367. ok = self.SendToRead(instruction = 'raster', text = line)
  368. if not ok: return False
  369. elif line.startswith('mapinfo'):
  370. instruction = 'mapinfo'
  371. isBuffer = True
  372. buffer.append(line)
  373. elif line.startswith('scalebar'):
  374. instruction = 'scalebar'
  375. isBuffer = True
  376. buffer.append(line)
  377. elif line.startswith('text'):
  378. instruction = 'text'
  379. isBuffer = True
  380. buffer.append(line)
  381. elif line.startswith('eps'):
  382. instruction = 'eps'
  383. isBuffer = True
  384. buffer.append(line)
  385. elif line.startswith('colortable'):
  386. if len(line.split()) == 2 and line.split()[1].lower() in ('n', 'no', 'none'):
  387. break
  388. instruction = 'colortable'
  389. isBuffer = True
  390. buffer.append(line)
  391. elif line.startswith('vlegend'):
  392. instruction = 'vlegend'
  393. isBuffer = True
  394. buffer.append(line)
  395. elif line.startswith('vpoints'):
  396. instruction = 'vpoints'
  397. isBuffer = True
  398. buffer.append(line)
  399. elif line.startswith('vlines'):
  400. instruction = 'vlines'
  401. isBuffer = True
  402. buffer.append(line)
  403. elif line.startswith('vareas'):
  404. instruction = 'vareas'
  405. isBuffer = True
  406. buffer.append(line)
  407. rasterLegend = self.FindInstructionByType('rasterLegend')
  408. raster = self.FindInstructionByType('raster')
  409. page = self.FindInstructionByType('page')
  410. vector = self.FindInstructionByType('vector')
  411. vectorLegend = self.FindInstructionByType('vectorLegend')
  412. vectorMaps = self.FindInstructionByType('vProperties', list = True)
  413. # check (in case of scaletype 0) if map is drawn also
  414. map['drawMap'] = False
  415. if map['scaleType'] == 0:
  416. mapForRegion = map['map']
  417. if map['mapType'] == 'raster' and raster:
  418. if mapForRegion == raster['raster']:
  419. map['drawMap'] = True
  420. elif map['mapType'] == 'vector' and vector:
  421. for vmap in vector['list']:
  422. if mapForRegion == vmap[0]:
  423. map['drawMap'] = True
  424. # rasterLegend
  425. if rasterLegend:
  426. if rasterLegend['rasterDefault'] and raster:
  427. rasterLegend['raster'] = raster['raster']
  428. if not rasterLegend['discrete']:
  429. rasterType = getRasterType(map = rasterLegend['raster'])
  430. if rasterType == 'CELL':
  431. rasterLegend['discrete'] = 'y'
  432. else:
  433. rasterLegend['discrete'] = 'n'
  434. #estimate size
  435. height = rasterLegend.EstimateHeight(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'],
  436. fontsize = rasterLegend['fontsize'],
  437. cols = rasterLegend['cols'],
  438. height = rasterLegend['height'])
  439. width = rasterLegend.EstimateWidth(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'],
  440. fontsize = rasterLegend['fontsize'],
  441. cols = rasterLegend['cols'] ,
  442. width = rasterLegend['width'],
  443. paperInstr = page)
  444. rasterLegend['rect'] = wx.Rect2D(x = float(rasterLegend['where'][0]), y = float(rasterLegend['where'][1]),
  445. w = width, h = height)
  446. # vectors, vlegend
  447. if vector:
  448. for vmap in vectorMaps:
  449. for i, each in enumerate(vector['list']):
  450. if each[2] == vmap.id:
  451. vector['list'][i][4] = vmap['label']
  452. vector['list'][i][3] = vmap['lpos']
  453. if vectorLegend:
  454. size = vectorLegend.EstimateSize(vectorInstr = vector, fontsize = vectorLegend['fontsize'],
  455. width = vectorLegend['width'], cols = vectorLegend['cols'])
  456. vectorLegend['rect'] = wx.Rect2D(x = float(vectorLegend['where'][0]), y = float(vectorLegend['where'][1]),
  457. w = size[0], h = size[1])
  458. page = self.FindInstructionByType('page')
  459. if not page:
  460. page = PageSetup(wx.NewId())
  461. self.AddInstruction(page)
  462. else:
  463. page['Orientation'] = orientation
  464. #
  465. return True
  466. def SendToRead(self, instruction, text, **kwargs):
  467. psmapInstrDict = dict(paper = ['page'],
  468. maploc = ['map'],
  469. scale = ['map'],
  470. border = ['map'],
  471. raster = ['raster'],
  472. mapinfo = ['mapinfo'],
  473. scalebar = ['scalebar'],
  474. text = ['text'],
  475. eps = ['image', 'northArrow'],
  476. vpoints = ['vector', 'vProperties'],
  477. vlines = ['vector', 'vProperties'],
  478. vareas = ['vector', 'vProperties'],
  479. colortable = ['rasterLegend'],
  480. vlegend = ['vectorLegend']
  481. )
  482. myInstrDict = dict(page = PageSetup,
  483. map = MapFrame,
  484. raster = Raster,
  485. mapinfo = Mapinfo,
  486. scalebar = Scalebar,
  487. text = Text,
  488. image = Image,
  489. northArrow = NorthArrow,
  490. rasterLegend = RasterLegend,
  491. vectorLegend = VectorLegend,
  492. vector = Vector,
  493. vProperties = VProperties
  494. )
  495. myInstruction = psmapInstrDict[instruction]
  496. for i in myInstruction:
  497. instr = self.FindInstructionByType(i)
  498. if i in ('text', 'vProperties', 'image', 'northArrow') or not instr:
  499. id = wx.NewId() #!vProperties expect subtype
  500. if i == 'vProperties':
  501. id = kwargs['id']
  502. newInstr = myInstrDict[i](id, subType = instruction[1:])
  503. elif i in ('image', 'northArrow'):
  504. commentFound = False
  505. for line in text:
  506. if line.find("# north arrow") >= 0:
  507. commentFound = True
  508. if i == 'image' and commentFound or \
  509. i == 'northArrow' and not commentFound:
  510. continue
  511. newInstr = myInstrDict[i](id, settings = self)
  512. else:
  513. newInstr = myInstrDict[i](id)
  514. ok = newInstr.Read(instruction, text, **kwargs)
  515. if ok:
  516. self.AddInstruction(newInstr)
  517. else:
  518. return False
  519. else:
  520. ok = instr.Read(instruction, text, **kwargs)
  521. if not ok:
  522. return False
  523. return True
  524. def SetRegion(self, regionInstruction):
  525. """!Sets region from file comment or sets current region in case of no comment"""
  526. map = MapFrame(wx.NewId())
  527. self.AddInstruction(map)
  528. if regionInstruction:
  529. cmd = CmdToTuple(regionInstruction.strip('# ').split())
  530. # define scaleType
  531. if len(cmd[1]) <= 3:
  532. if 'rast' in cmd[1]:
  533. map['scaleType'] = 0
  534. map['mapType'] = 'raster'
  535. map['map'] = cmd[1]['rast']
  536. elif 'vect' in cmd[1]:
  537. map['scaleType'] = 0
  538. map['mapType'] = 'vector'
  539. map['map'] = cmd[1]['vect']
  540. elif 'region' in cmd[1]:
  541. map['scaleType'] = 1
  542. map['region'] = cmd[1]['region']
  543. else:
  544. map['scaleType'] = 2
  545. else:
  546. map['scaleType'] = 2
  547. grass.del_temp_region()
  548. region = grass.region()
  549. grass.use_temp_region()
  550. cmd = ['g.region', region]
  551. cmdString = GetCmdString(cmd).replace('g.region', '')
  552. GMessage(_("Instruction file will be loaded with following region: %s\n") % cmdString)
  553. try:
  554. RunCommand(cmd[0], **cmd[1])
  555. except grass.ScriptError, e:
  556. GError(_("Region cannot be set\n%s") % e)
  557. return False
  558. class InstructionObject:
  559. """!Abtract class representing single instruction"""
  560. def __init__(self, id):
  561. self.id = id
  562. # default values
  563. self.defaultInstruction = dict()
  564. # current values
  565. self.instruction = self.defaultInstruction
  566. # converting units
  567. self.unitConv = UnitConversion()
  568. def __str__(self):
  569. """!Returns particular part of text instruction"""
  570. return ''
  571. def __getitem__(self, key):
  572. for each in self.instruction.keys():
  573. if each == key:
  574. return self.instruction[key]
  575. return None
  576. def __setitem__(self, key, value):
  577. self.instruction[key] = value
  578. def GetInstruction(self):
  579. """!Get current values"""
  580. return self.instruction
  581. def SetInstruction(self, instruction):
  582. """!Set default values"""
  583. self.instruction = instruction
  584. def Read(self, instruction, text, **kwargs):
  585. """!Read instruction and save them"""
  586. pass
  587. class InitMap(InstructionObject):
  588. """!Class representing virtual map"""
  589. def __init__(self, id):
  590. InstructionObject.__init__(self, id = id)
  591. self.type = 'initMap'
  592. # default values
  593. self.defaultInstruction = dict(rect = None, scale = None)
  594. # current values
  595. self.instruction = dict(self.defaultInstruction)
  596. class MapFrame(InstructionObject):
  597. """!Class representing map (instructions maploc, scale, border)"""
  598. def __init__(self, id):
  599. InstructionObject.__init__(self, id = id)
  600. self.type = 'map'
  601. # default values
  602. self.defaultInstruction = dict(map = None, mapType = None, drawMap = True, region = None,
  603. rect = wx.Rect2D(), scaleType = 0, scale = None, center = None,
  604. resolution = 300, border = 'y', width = 1, color = '0:0:0')
  605. # current values
  606. self.instruction = dict(self.defaultInstruction)
  607. def __str__(self):
  608. instr = ''
  609. comment = ''
  610. #region settings
  611. region = grass.region()
  612. if self.instruction['scaleType'] == 0: #match map
  613. map = self.instruction['map']
  614. if self.instruction['mapType'] == 'raster':
  615. comment = "# g.region rast=%s nsres=%s ewres=%s\n" % (map, region['nsres'], region['ewres'])
  616. else:
  617. comment = "# g.region vect=%s\n" % (map)
  618. elif self.instruction['scaleType'] == 1:# saved region
  619. region = self.instruction['region']
  620. comment = "# g.region region=%s\n" % region
  621. elif self.instruction['scaleType'] in (2, 3): #current region, fixed scale
  622. comment = string.Template("# g.region n=$n s=$s e=$e w=$w rows=$rows cols=$cols \n").substitute(**region)
  623. instr += comment
  624. instr += '\n'
  625. # maploc
  626. maplocInstruction = "maploc %.3f %.3f" % (self.instruction['rect'].x, self.instruction['rect'].y)
  627. if self.instruction['scaleType'] != 3:
  628. maplocInstruction += " %.3f %.3f"% (self.instruction['rect'].width, self.instruction['rect'].height)
  629. instr += maplocInstruction
  630. instr += '\n'
  631. # scale
  632. if self.instruction['scaleType'] == 3: #fixed scale
  633. scaleInstruction = "scale 1:%.0f" % (1/self.instruction['scale'])
  634. instr += scaleInstruction
  635. instr += '\n'
  636. # border
  637. borderInstruction = ''
  638. if self.instruction['border'] == 'n':
  639. borderInstruction = "border n"
  640. else:
  641. borderInstruction = "border y\n"
  642. borderInstruction += string.Template(" width $width\n color $color\n").substitute(self.instruction)
  643. borderInstruction += " end"
  644. instr += borderInstruction
  645. instr += '\n'
  646. return instr
  647. def Read(self, instruction, text, **kwargs):
  648. """!Read instruction and save information"""
  649. if 'isRegionComment' in kwargs:
  650. isRegionComment = kwargs['isRegionComment']
  651. instr = {}
  652. if instruction == 'border':
  653. for line in text:
  654. if line.startswith('end'):
  655. break
  656. try:
  657. if line.split()[1].lower() in ('n', 'no', 'none'):
  658. instr['border'] = 'n'
  659. break
  660. elif line.split()[1].lower() in ('y', 'yes'):
  661. instr['border'] = 'y'
  662. elif line.startswith('width'):
  663. instr['width'] = line.split()[1]
  664. elif line.startswith('color'):
  665. instr['color'] = line.split()[1]
  666. except IndexError:
  667. GError(_("Failed to read instruction %s") % instruction)
  668. return False
  669. elif instruction == 'scale':
  670. try:
  671. scaleText = text.strip('scale ').split(':')[1]
  672. # when scale instruction given and region comment also, then scaletype is fixed scale
  673. if not isRegionComment:
  674. instr['scaleType'] = 2
  675. else:
  676. instr['scaleType'] = 3
  677. scale = 1/float(scaleText)
  678. if abs(scale - self.instruction['scale']) > (0.01 * scale):
  679. GWarning(_("Scale has changed, old value: %(old)s\nnew value: %(new)s") % \
  680. { 'old' : scale, 'new' : self.instruction['scale'] })
  681. except (ValueError, IndexError):
  682. GError(_("Failed to read instruction %s.\nUse 1:25000 notation.") % instruction)
  683. return False
  684. elif instruction == 'maploc':
  685. maploc = text.strip('maploc ').split()
  686. if len(maploc) >= 2:
  687. if abs(self.instruction['rect'].Get()[0] - float(maploc[0])) > 0.5 or \
  688. abs(self.instruction['rect'].Get()[1] - float(maploc[1])) > 0.5:
  689. GWarning(_("Map frame position changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \
  690. { 'old1' : maploc[0], 'old2' : maploc[1],
  691. 'new1' : self.instruction['rect'].Get()[0], 'new2' : self.instruction['rect'].Get()[1] })
  692. #instr['rect'] = wx.Rect2D(float(maploc[0]), float(maploc[1]), self.instruction['rect'][2], self.instruction['rect'][3])
  693. if len(maploc) == 4:
  694. if abs(self.instruction['rect'].Get()[2] - float(maploc[2])) > 0.5 or \
  695. abs(self.instruction['rect'].Get()[3] - float(maploc[3])) > 0.5:
  696. GWarning(_("Map frame size changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \
  697. { 'old1' : maploc[2], 'old2' : maploc[3],
  698. 'new1' : self.instruction['rect'].Get()[2], 'new2' : self.instruction['rect'].Get()[3] })
  699. #instr['rect'] = wx.Rect2D(*map(float, maploc))
  700. self.instruction.update(instr)
  701. return True
  702. class PageSetup(InstructionObject):
  703. """!Class representing page instruction"""
  704. def __init__(self, id):
  705. InstructionObject.__init__(self, id = id)
  706. self.type = 'page'
  707. # default values
  708. self.defaultInstruction = dict(Units = 'inch', Format = 'a4', Orientation = 'Portrait',
  709. Width = 8.268, Height = 11.693, Left = 0.5, Right = 0.5, Top = 1, Bottom = 1)
  710. # current values
  711. self.instruction = dict(self.defaultInstruction)
  712. def __str__(self):
  713. if self.instruction['Format'] == 'custom':
  714. instr = string.Template("paper\n width $Width\n height $Height\n").substitute(self.instruction)
  715. else:
  716. instr = string.Template("paper $Format\n").substitute(self.instruction)
  717. instr += string.Template(" left $Left\n right $Right\n bottom $Bottom\n top $Top\n end").substitute(self.instruction)
  718. return instr
  719. def Read(self, instruction, text, **kwargs):
  720. """!Read instruction and save information"""
  721. instr = {}
  722. self.cats = ['Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
  723. self.subInstr = dict(zip(['width', 'height', 'left', 'right', 'top', 'bottom'], self.cats))
  724. if instruction == 'paper': # just for sure
  725. for line in text:
  726. if line.startswith('paper'):
  727. if len(line.split()) > 1:
  728. pformat = line.split()[1]
  729. availableFormats = self._toDict(grass.read_command('ps.map', flags = 'p',
  730. quiet = True))
  731. # e.g. paper a3
  732. try:
  733. instr['Format'] = pformat
  734. for key, value in availableFormats[pformat].iteritems():
  735. instr[key] = float(value)
  736. break
  737. except KeyError:
  738. GError(_("Failed to read instruction %(file)s.\nUnknown format %(for)s") % \
  739. { 'file' : instruction, 'for' : format })
  740. return False
  741. else:
  742. # paper
  743. # width ...
  744. instr['Format'] = 'custom'
  745. # read subinstructions
  746. elif instr['Format'] == 'custom' and not line.startswith('end'):
  747. text = line.split()
  748. try:
  749. instr[self.subInstr[text[0]]] = float(text[1])
  750. except (IndexError, KeyError):
  751. GError(_("Failed to read instruction %s.") % instruction)
  752. return False
  753. if 'Orientation' in kwargs and kwargs['Orientation'] == 'Landscape':
  754. instr['Width'], instr['Height'] = instr['Height'], instr['Width']
  755. self.instruction.update(instr)
  756. return True
  757. def _toDict(self, paperStr):
  758. sizeDict = dict()
  759. # cats = self.subInstr[ 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
  760. for line in paperStr.strip().split('\n'):
  761. d = dict(zip(self.cats, line.split()[1:]))
  762. sizeDict[line.split()[0]] = d
  763. return sizeDict
  764. class Mapinfo(InstructionObject):
  765. """!Class representing mapinfo instruction"""
  766. def __init__(self, id):
  767. InstructionObject.__init__(self, id = id)
  768. self.type = 'mapinfo'
  769. # default values
  770. self.defaultInstruction = dict(unit = 'inch', where = (0, 0),
  771. font = 'Helvetica', fontsize = 10, color = '0:0:0', background = 'none',
  772. border = 'none', rect = None)
  773. # current values
  774. self.instruction = dict(self.defaultInstruction)
  775. def __str__(self):
  776. instr = "mapinfo\n"
  777. instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
  778. instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n").substitute(self.instruction)
  779. instr += string.Template(" background $background\n border $border\n").substitute(self.instruction)
  780. instr += " end"
  781. return instr
  782. def Read(self, instruction, text):
  783. """!Read instruction and save information"""
  784. instr = {}
  785. try:
  786. for line in text:
  787. sub = line.split(None,1)
  788. if sub[0] == 'font':
  789. instr['font'] = sub[1]
  790. elif sub[0] == 'fontsize':
  791. instr['fontsize'] = int(sub[1])
  792. elif sub[0] == 'color':
  793. instr['color'] = sub[1]
  794. elif sub[0] == 'background':
  795. instr['background'] = sub[1]
  796. elif sub[0] == 'border':
  797. instr['border'] = sub[1]
  798. elif sub[0] == 'where':
  799. instr['where'] = float(sub[1].split()[0]), float(sub[1].split()[1])
  800. except (ValueError, IndexError):
  801. GError(_("Failed to read instruction %s") % instruction)
  802. return False
  803. self.instruction.update(instr)
  804. self.instruction['rect'] = self.EstimateRect(mapinfoDict = self.instruction)
  805. return True
  806. def EstimateRect(self, mapinfoDict):
  807. """!Estimate size to draw mapinfo"""
  808. w = mapinfoDict['fontsize'] * 20 # any better estimation?
  809. h = mapinfoDict['fontsize'] * 7
  810. width = self.unitConv.convert(value = w, fromUnit = 'point', toUnit = 'inch')
  811. height = self.unitConv.convert(value = h, fromUnit = 'point', toUnit = 'inch')
  812. return wx.Rect2D(x = float(mapinfoDict['where'][0]), y = float(mapinfoDict['where'][1]), w = width, h = height)
  813. class Text(InstructionObject):
  814. """!Class representing text instruction"""
  815. def __init__(self, id):
  816. InstructionObject.__init__(self, id = id)
  817. self.type = 'text'
  818. # default values
  819. self.defaultInstruction = dict(text = "", font = "Helvetica", fontsize = 10, color = 'black', background = 'none',
  820. hcolor = 'none', hwidth = 1, border = 'none', width = '1', XY = True,
  821. where = (0,0), unit = 'inch', rotate = None,
  822. ref = "center center", xoffset = 0, yoffset = 0, east = None, north = None)
  823. # current values
  824. self.instruction = dict(self.defaultInstruction)
  825. def __str__(self):
  826. text = self.instruction['text'].replace('\n','\\n')
  827. instr = "text %s %s" % (self.instruction['east'], self.instruction['north'])
  828. try:
  829. instr += " %s\n" % text.encode('latin_1')
  830. except UnicodeEncodeError, err:
  831. try:
  832. pos = str(err).split('position')[1].split(':')[0].strip()
  833. except IndexError:
  834. pos = ''
  835. if pos:
  836. message = _("Characters on position %s are not supported "
  837. "by ISO-8859-1 (Latin 1) encoding "
  838. "which is required by module ps.map.") % pos
  839. else:
  840. message = _("Not all characters are supported "
  841. "by ISO-8859-1 (Latin 1) encoding "
  842. "which is required by module ps.map.")
  843. GMessage(message = message)
  844. return ''
  845. instr += (string.Template(" font $font\n fontsize $fontsize\n color $color\n").
  846. substitute(self.instruction).
  847. encode('latin_1'))
  848. instr += string.Template(" hcolor $hcolor\n").substitute(self.instruction).encode('latin_1')
  849. if self.instruction['hcolor'] != 'none':
  850. instr += string.Template(" hwidth $hwidth\n").substitute(self.instruction).encode('latin_1')
  851. instr += string.Template(" border $border\n").substitute(self.instruction).encode('latin_1')
  852. if self.instruction['border'] != 'none':
  853. instr += string.Template(" width $width\n").substitute(self.instruction).encode('latin_1')
  854. instr += string.Template(" background $background\n").substitute(self.instruction).encode('latin_1')
  855. if self.instruction["ref"] != '0':
  856. instr += string.Template(" ref $ref\n").substitute(self.instruction).encode('latin_1')
  857. if self.instruction["rotate"]:
  858. instr += string.Template(" rotate $rotate\n").substitute(self.instruction).encode('latin_1')
  859. if float(self.instruction["xoffset"]) or float(self.instruction["yoffset"]):
  860. instr += (string.Template(" xoffset $xoffset\n yoffset $yoffset\n").
  861. substitute(self.instruction).encode('latin_1'))
  862. instr += " end"
  863. return instr
  864. def Read(self, instruction, text, **kwargs):
  865. """!Read instruction and save information"""
  866. map = kwargs['mapInstruction']
  867. instr = {}
  868. for line in text:
  869. try:
  870. sub = line.split(None, 1)[0]
  871. if sub == 'text':
  872. e, n = line.split(None, 3)[1:3]
  873. if '%' in e and '%' in n:
  874. instr['XY'] = True
  875. instr['east'], instr['north'] = self.PercentToReal(e, n)
  876. else:
  877. instr['XY'] = False
  878. instr['east'], instr['north'] = float(e), float(n)
  879. instr['text'] = line.split(None, 3)[3]
  880. elif sub == 'font':
  881. instr['font'] = line.split(None, 1)[1]
  882. elif sub == 'fontsize':
  883. instr['fontsize'] = float(line.split(None, 1)[1])
  884. elif sub == 'color':
  885. instr['color'] = line.split(None, 1)[1]
  886. elif sub == 'width':
  887. instr['width'] = line.split(None, 1)[1]
  888. elif sub == 'hcolor':
  889. instr['hcolor'] = line.split(None, 1)[1]
  890. elif sub == 'hwidth':
  891. instr['hwidth'] = line.split(None, 1)[1]
  892. elif sub == 'background':
  893. instr['background'] = line.split(None, 1)[1]
  894. elif sub == 'border':
  895. instr['border'] = line.split(None, 1)[1]
  896. elif sub == 'ref':
  897. instr['ref'] = line.split(None, 1)[1]
  898. elif sub == 'rotate':
  899. instr['rotate'] = float(line.split(None, 1)[1])
  900. elif sub == 'xoffset':
  901. instr['xoffset'] = int(line.split(None, 1)[1])
  902. elif sub == 'yoffset':
  903. instr['yoffset'] = int(line.split(None, 1)[1])
  904. elif sub == 'opaque':
  905. if line.split(None, 1)[1].lower() in ('n', 'none'):
  906. instr['background'] = 'none'
  907. except(IndexError, ValueError):
  908. GError(_("Failed to read instruction %s") % instruction)
  909. return False
  910. instr['where'] = PaperMapCoordinates(map = map, x = instr['east'], y = instr['north'], paperToMap = False)
  911. self.instruction.update(instr)
  912. return True
  913. def PercentToReal(self, e, n):
  914. """!Converts text coordinates from percent of region to map coordinates"""
  915. e, n = float(e.strip('%')), float(n.strip('%'))
  916. region = grass.region()
  917. N = region['s'] + (region['n'] - region['s']) / 100 * n
  918. E = region['w'] + (region['e'] - region['w']) / 100 * e
  919. return E, N
  920. class Image(InstructionObject):
  921. """!Class representing eps instruction - image"""
  922. def __init__(self, id, settings):
  923. InstructionObject.__init__(self, id = id)
  924. self.settings = settings
  925. self.type = 'image'
  926. # default values
  927. self.defaultInstruction = dict(epsfile = "", XY = True, where = (0,0), unit = 'inch',
  928. east = None, north = None,
  929. rotate = None, scale = 1)
  930. # current values
  931. self.instruction = dict(self.defaultInstruction)
  932. def __str__(self):
  933. self.ChangeRefPoint(toCenter = True)
  934. instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
  935. instr += string.Template(" epsfile $epsfile\n").substitute(self.instruction)
  936. if self.instruction["rotate"]:
  937. instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
  938. if self.instruction["scale"]:
  939. instr += string.Template(" scale $scale\n").substitute(self.instruction)
  940. instr += " end"
  941. return instr
  942. def Read(self, instruction, text, **kwargs):
  943. """!Read instruction and save information"""
  944. mapInstr = kwargs['mapInstruction']
  945. instr = {}
  946. for line in text:
  947. try:
  948. sub = line.split(None, 1)[0]
  949. if sub == 'eps':
  950. e, n = line.split(None, 3)[1:3]
  951. if '%' in e and '%' in n:
  952. instr['XY'] = True
  953. instr['east'], instr['north'] = self.PercentToReal(e, n)
  954. else:
  955. instr['XY'] = False
  956. instr['east'], instr['north'] = float(e), float(n)
  957. elif sub == 'epsfile':
  958. instr['epsfile'] = line.split(None, 1)[1]
  959. elif sub == 'rotate':
  960. instr['rotate'] = float(line.split(None, 1)[1])
  961. elif sub == 'scale':
  962. instr['scale'] = float(line.split(None, 1)[1])
  963. except(IndexError, ValueError):
  964. GError(_("Failed to read instruction %s") % instruction)
  965. return False
  966. if not os.path.exists(instr['epsfile']):
  967. GError(_("Failed to read instruction %s: file %s not found.") % instruction, instr['epsfile'])
  968. return False
  969. instr['epsfile'] = os.path.abspath(instr['epsfile'])
  970. instr['size'] = self.GetImageOrigSize(instr['epsfile'])
  971. if 'rotate' in instr:
  972. instr['size'] = BBoxAfterRotation(instr['size'][0], instr['size'][1], instr['rotate'])
  973. self.instruction.update(instr)
  974. self.ChangeRefPoint(toCenter = False)
  975. instr['where'] = PaperMapCoordinates(map = mapInstr, x = self.instruction['east'],
  976. y = self.instruction['north'], paperToMap = False)
  977. w = self.unitConv.convert(value = instr['size'][0], fromUnit = 'point', toUnit = 'inch')
  978. h = self.unitConv.convert(value = instr['size'][1], fromUnit = 'point', toUnit = 'inch')
  979. instr['rect'] = wx.Rect2D(x = float(instr['where'][0]), y = float(instr['where'][1]),
  980. w = w * self.instruction['scale'], h = h * self.instruction['scale'])
  981. self.instruction.update(instr)
  982. return True
  983. def PercentToReal(self, e, n):
  984. """!Converts eps coordinates from percent of region to map coordinates"""
  985. e, n = float(e.strip('%')), float(n.strip('%'))
  986. region = grass.region()
  987. N = region['s'] + (region['n'] - region['s']) / 100 * n
  988. E = region['w'] + (region['e'] - region['w']) / 100 * e
  989. return E, N
  990. def ChangeRefPoint(self, toCenter):
  991. """!Change reference point (left top x center)"""
  992. mapInstr = self.settings.FindInstructionByType('map')
  993. if not mapInstr:
  994. mapInstr = self.settings.FindInstructionByType('initMap')
  995. mapId = mapInstr.id
  996. if toCenter:
  997. center = self.instruction['rect'].GetCentre()
  998. ENCenter = PaperMapCoordinates(map = self.settings[mapId],
  999. x = center[0], y = center[1], paperToMap = True)
  1000. self.instruction['east'], self.instruction['north'] = ENCenter
  1001. else:
  1002. x, y = PaperMapCoordinates(map = self.settings[mapId], x = self.instruction['east'],
  1003. y = self.instruction['north'], paperToMap = False)
  1004. w = self.unitConv.convert(value = self.instruction['size'][0], fromUnit = 'point', toUnit = 'inch')
  1005. h = self.unitConv.convert(value = self.instruction['size'][1], fromUnit = 'point', toUnit = 'inch')
  1006. x -= w * self.instruction['scale'] / 2
  1007. y -= h * self.instruction['scale'] / 2
  1008. e, n = PaperMapCoordinates(map = self.settings[mapId], x = x, y = y, paperToMap = True)
  1009. self.instruction['east'], self.instruction['north'] = e, n
  1010. def GetImageOrigSize(self, imagePath):
  1011. """!Get image size.
  1012. If eps, size is read from image header.
  1013. """
  1014. fileName = os.path.split(imagePath)[1]
  1015. # if eps, read info from header
  1016. if os.path.splitext(fileName)[1].lower() == '.eps':
  1017. bbInfo = "%%BoundingBox"
  1018. file = open(imagePath,"r")
  1019. w = h = 0
  1020. while file:
  1021. line = file.readline()
  1022. if line.find(bbInfo) == 0:
  1023. w, h = line.split()[3:5]
  1024. break
  1025. file.close()
  1026. return float(w), float(h)
  1027. else: # we can use wx.Image
  1028. img = wx.Image(fileName, type=wx.BITMAP_TYPE_ANY)
  1029. return img.GetWidth(), img.GetHeight()
  1030. class NorthArrow(Image):
  1031. """!Class representing eps instruction -- North Arrow"""
  1032. def __init__(self, id, settings):
  1033. Image.__init__(self, id = id, settings = settings)
  1034. self.type = 'northArrow'
  1035. def __str__(self):
  1036. self.ChangeRefPoint(toCenter = True)
  1037. instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
  1038. instr += "# north arrow\n"
  1039. instr += string.Template(" epsfile $epsfile\n").substitute(self.instruction)
  1040. if self.instruction["rotate"]:
  1041. instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
  1042. if self.instruction["scale"]:
  1043. instr += string.Template(" scale $scale\n").substitute(self.instruction)
  1044. instr += " end"
  1045. return instr
  1046. class Scalebar(InstructionObject):
  1047. """!Class representing scalebar instruction"""
  1048. def __init__(self, id):
  1049. InstructionObject.__init__(self, id = id)
  1050. self.type = 'scalebar'
  1051. # default values
  1052. self.defaultInstruction = dict(unit = 'inch', where = (1,1),
  1053. unitsLength = 'auto', unitsHeight = 'inch',
  1054. length = None, height = 0.1, rect = None,
  1055. fontsize = 10, background = 'y',
  1056. scalebar = 'f', segment = 4, numbers = 1)
  1057. # current values
  1058. self.instruction = dict(self.defaultInstruction)
  1059. def __str__(self):
  1060. instr = string.Template("scalebar $scalebar\n").substitute(self.instruction)
  1061. instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
  1062. instr += string.Template(" length $length\n units $unitsLength\n").substitute(self.instruction)
  1063. instr += string.Template(" height $height\n").substitute(self.instruction)
  1064. instr += string.Template(" segment $segment\n numbers $numbers\n").substitute(self.instruction)
  1065. instr += string.Template(" fontsize $fontsize\n background $background\n").substitute(self.instruction)
  1066. instr += " end"
  1067. return instr
  1068. def Read(self, instruction, text, **kwargs):
  1069. """!Read instruction and save information"""
  1070. scale = kwargs['scale']
  1071. instr = {}
  1072. for line in text:
  1073. try:
  1074. if line.startswith('scalebar'):
  1075. if 'scalebar s' in line:
  1076. instr['scalebar'] = 's'
  1077. else:
  1078. instr['scalebar'] = 'f'
  1079. elif line.startswith('where'):
  1080. instr['where'] = map(float, line.split()[1:3])
  1081. elif line.startswith('length'):
  1082. instr['length'] = float(line.split()[1])
  1083. elif line.startswith('units'):
  1084. if line.split()[1] in ['auto', 'meters', 'kilometers', 'feet', 'miles', 'nautmiles']:
  1085. instr['unitsLength'] = line.split()[1]
  1086. elif line.startswith('height'):
  1087. instr['height'] = float(line.split()[1])
  1088. elif line.startswith('fontsize'):
  1089. instr['fontsize'] = float(line.split()[1])
  1090. elif line.startswith('numbers'):
  1091. instr['numbers'] = int(line.split()[1])
  1092. elif line.startswith('segment'):
  1093. instr['segment'] = int(line.split()[1])
  1094. elif line.startswith('background'):
  1095. if line.split()[1].strip().lower() in ('y','yes'):
  1096. instr['background'] = 'y'
  1097. elif line.split()[1].strip().lower() in ('n','no', 'none'):
  1098. instr['background'] = 'n'
  1099. except(IndexError, ValueError):
  1100. GError(_("Failed to read instruction %s") % instruction)
  1101. return False
  1102. self.instruction.update(instr)
  1103. w, h = self.EstimateSize(scalebarDict = self.instruction, scale = scale)
  1104. x = self.instruction['where'][0] - w / 2
  1105. y = self.instruction['where'][1] - h / 2
  1106. self.instruction['rect'] = wx.Rect2D(x, y, w, h)
  1107. return True
  1108. def EstimateSize(self, scalebarDict, scale):
  1109. """!Estimate size to draw scalebar"""
  1110. units = projInfo()['units']
  1111. if not units or units not in self.unitConv.getAllUnits():
  1112. units = 'meters'
  1113. if scalebarDict['unitsLength'] != 'auto':
  1114. length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = scalebarDict['unitsLength'], toUnit = 'inch')
  1115. else:
  1116. length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = units, toUnit = 'inch')
  1117. length *= scale
  1118. length *= 1.1 #for numbers on the edge
  1119. height = scalebarDict['height'] + 2 * self.unitConv.convert(value = scalebarDict['fontsize'], fromUnit = 'point', toUnit = 'inch')
  1120. return (length, height)
  1121. class RasterLegend(InstructionObject):
  1122. """!Class representing colortable instruction"""
  1123. def __init__(self, id):
  1124. InstructionObject.__init__(self, id = id)
  1125. self.type = 'rasterLegend'
  1126. # default values
  1127. self.defaultInstruction = dict(rLegend = False, unit = 'inch', rasterDefault = True, raster = None,
  1128. discrete = None, type = None,
  1129. where = (0, 0),
  1130. width = None, height = None, cols = 1, font = "Helvetica", fontsize = 10,
  1131. #color = '0:0:0', tickbar = False, range = False, min = 0, max = 0,
  1132. color = 'black', tickbar = 'n', range = False, min = 0, max = 0,
  1133. nodata = 'n')
  1134. # current values
  1135. self.instruction = dict(self.defaultInstruction)
  1136. def __str__(self):
  1137. instr = "colortable y\n"
  1138. instr += string.Template(" raster $raster\n").substitute(self.instruction)
  1139. instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
  1140. if self.instruction['width']:
  1141. instr += string.Template(" width $width\n").substitute(self.instruction)
  1142. instr += string.Template(" discrete $discrete\n").substitute(self.instruction)
  1143. if self.instruction['discrete'] == 'n':
  1144. if self.instruction['height']:
  1145. instr += string.Template(" height $height\n").substitute(self.instruction)
  1146. instr += string.Template(" tickbar $tickbar\n").substitute(self.instruction)
  1147. if self.instruction['range']:
  1148. instr += string.Template(" range $min $max\n").substitute(self.instruction)
  1149. else:
  1150. instr += string.Template(" cols $cols\n").substitute(self.instruction)
  1151. instr += string.Template(" nodata $nodata\n").substitute(self.instruction)
  1152. instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n")\
  1153. .substitute(self.instruction)
  1154. instr += " end"
  1155. return instr
  1156. def Read(self, instruction, text, **kwargs):
  1157. """!Read instruction and save information"""
  1158. instr = {}
  1159. instr['rLegend'] = True
  1160. for line in text:
  1161. try:
  1162. if line.startswith('where'):
  1163. instr['where'] = map(float, line.split()[1:3])
  1164. elif line.startswith('font '):
  1165. instr['font'] = line.split()[1]
  1166. elif line.startswith('fontsize'):
  1167. instr['fontsize'] = float(line.split()[1])
  1168. elif line.startswith('color '):
  1169. instr['color'] = line.split()[1]
  1170. elif line.startswith('raster'):
  1171. instr['raster'] = line.split()[1]
  1172. elif line.startswith('width'):
  1173. instr['width'] = float(line.split()[1])
  1174. elif line.startswith('height'):
  1175. instr['height'] = float(line.split()[1])
  1176. elif line.startswith('cols'):
  1177. instr['cols'] = int(line.split()[1])
  1178. elif line.startswith('range'):
  1179. instr['range'] = True
  1180. instr['min'] = float(line.split()[1])
  1181. instr['max'] = float(line.split()[2])
  1182. elif line.startswith('nodata'):
  1183. if line.split()[1].strip().lower() in ('y','yes'):
  1184. instr['nodata'] = 'y'
  1185. elif line.split()[1].strip().lower() in ('n','no', 'none'):
  1186. instr['nodata'] = 'n'
  1187. elif line.startswith('tickbar'):
  1188. if line.split()[1].strip().lower() in ('y','yes'):
  1189. instr['tickbar'] = 'y'
  1190. elif line.split()[1].strip().lower() in ('n','no', 'none'):
  1191. instr['tickbar'] = 'n'
  1192. elif line.startswith('discrete'):
  1193. if line.split()[1].strip().lower() in ('y','yes'):
  1194. instr['discrete'] = 'y'
  1195. elif line.split()[1].strip().lower() in ('n','no', 'none'):
  1196. instr['discrete'] = 'n'
  1197. except(IndexError, ValueError):
  1198. GError(_("Failed to read instruction %s") % instruction)
  1199. return False
  1200. if 'raster' in instr:
  1201. instr['rasterDefault'] = False
  1202. if 'discrete' not in instr:
  1203. rasterType = getRasterType(map = instr['raster'])
  1204. instr['type'] = rasterType
  1205. if rasterType == 'CELL':
  1206. instr['discrete'] = 'y'
  1207. else:
  1208. instr['discrete'] = 'n'
  1209. else:
  1210. instr['rasterDefault'] = True
  1211. self.instruction.update(instr)
  1212. # add 'rect' in the end
  1213. return True
  1214. def EstimateHeight(self, raster, discrete, fontsize, cols = None, height = None):
  1215. """!Estimate height to draw raster legend"""
  1216. if discrete == 'n':
  1217. if height:
  1218. height = height
  1219. else:
  1220. height = self.unitConv.convert(value = fontsize * 10,
  1221. fromUnit = 'point', toUnit = 'inch')
  1222. if discrete == 'y':
  1223. if cols:
  1224. cols = cols
  1225. else:
  1226. cols = 1
  1227. rinfo = grass.raster_info(raster)
  1228. if rinfo['datatype'] in ('DCELL', 'FCELL'):
  1229. minim, maxim = rinfo['min'], rinfo['max']
  1230. rows = ceil(maxim / cols )
  1231. else:
  1232. cat = grass.read_command('r.category', map = raster,
  1233. fs = ':').strip().split('\n')
  1234. rows = ceil(float(len(cat)) / cols )
  1235. height = self.unitConv.convert(value = 1.5 * rows * fontsize, fromUnit = 'point', toUnit = 'inch')
  1236. return height
  1237. def EstimateWidth(self, raster, discrete, fontsize, cols = None, width = None, paperInstr = None):
  1238. """!Estimate size to draw raster legend"""
  1239. if discrete == 'n':
  1240. rinfo = grass.raster_info(raster)
  1241. minim, maxim = rinfo['min'], rinfo['max']
  1242. if width:
  1243. width = width
  1244. else:
  1245. width = self.unitConv.convert(value = fontsize * 2,
  1246. fromUnit = 'point', toUnit = 'inch')
  1247. text = len(max(str(minim), str(maxim), key = len))
  1248. textPart = self.unitConv.convert(value = text * fontsize / 2,
  1249. fromUnit = 'point', toUnit = 'inch')
  1250. width += textPart
  1251. elif discrete == 'y':
  1252. if cols:
  1253. cols = cols
  1254. else:
  1255. cols = 1
  1256. if width:
  1257. width = width
  1258. else:
  1259. paperWidth = paperInstr['Width'] - paperInstr['Right'] - paperInstr['Left']
  1260. width = (paperWidth / cols) * (cols - 1) + 1
  1261. return width
  1262. class VectorLegend(InstructionObject):
  1263. """!Class representing colortable instruction"""
  1264. def __init__(self, id):
  1265. InstructionObject.__init__(self, id = id)
  1266. self.type = 'vectorLegend'
  1267. # default values
  1268. self.defaultInstruction = dict(vLegend = False, unit = 'inch', where = (0, 0),
  1269. defaultSize = True, width = 0.4, cols = 1, span = None,
  1270. font = "Helvetica", fontsize = 10,
  1271. border = 'none')
  1272. # current values
  1273. self.instruction = dict(self.defaultInstruction)
  1274. def __str__(self):
  1275. instr = "vlegend\n"
  1276. instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
  1277. instr += string.Template(" font $font\n fontsize $fontsize\n").substitute(self.instruction)
  1278. instr += string.Template(" width $width\n cols $cols\n").substitute(self.instruction)
  1279. if self.instruction['span']:
  1280. instr += string.Template(" span $span\n").substitute(self.instruction)
  1281. instr += string.Template(" border $border\n").substitute(self.instruction)
  1282. instr += " end"
  1283. return instr
  1284. def Read(self, instruction, text, **kwargs):
  1285. """!Read instruction and save information"""
  1286. instr = {}
  1287. instr['vLegend'] = True
  1288. for line in text:
  1289. try:
  1290. if line.startswith('where'):
  1291. instr['where'] = map(float, line.split()[1:3])
  1292. elif line.startswith('font '):
  1293. instr['font'] = line.split()[1]
  1294. elif line.startswith('fontsize'):
  1295. instr['fontsize'] = float(line.split()[1])
  1296. elif line.startswith('width'):
  1297. instr['width'] = float(line.split()[1])
  1298. elif line.startswith('cols'):
  1299. instr['cols'] = int(line.split()[1])
  1300. elif line.startswith('span'):
  1301. instr['span'] = float(line.split()[1])
  1302. elif line.startswith('border'):
  1303. instr['border'] = line.split()[1]
  1304. except(IndexError, ValueError):
  1305. GError(_("Failed to read instruction %s") % instruction)
  1306. return False
  1307. self.instruction.update(instr)
  1308. return True
  1309. def EstimateSize(self, vectorInstr, fontsize, width = None, cols = None):
  1310. """!Estimate size to draw vector legend"""
  1311. if width:
  1312. width = width
  1313. else:
  1314. width = fontsize/24.0
  1315. if cols:
  1316. cols = cols
  1317. else:
  1318. cols = 1
  1319. vectors = vectorInstr['list']
  1320. labels = [vector[4] for vector in vectors if vector[3] != 0]
  1321. extent = (len(max(labels, key = len)) * fontsize / 2, fontsize)
  1322. wExtent = self.unitConv.convert(value = extent[0], fromUnit = 'point', toUnit = 'inch')
  1323. hExtent = self.unitConv.convert(value = extent[1], fromUnit = 'point', toUnit = 'inch')
  1324. w = (width + wExtent) * cols
  1325. h = len(labels) * hExtent / cols
  1326. h *= 1.1
  1327. return (w, h)
  1328. class Raster(InstructionObject):
  1329. """!Class representing raster instruction"""
  1330. def __init__(self, id):
  1331. InstructionObject.__init__(self, id = id)
  1332. self.type = 'raster'
  1333. # default values
  1334. self.defaultInstruction = dict(isRaster = False, raster = None)
  1335. # current values
  1336. self.instruction = dict(self.defaultInstruction)
  1337. def __str__(self):
  1338. instr = string.Template("raster $raster").substitute(self.instruction)
  1339. return instr
  1340. def Read(self, instruction, text):
  1341. """!Read instruction and save information"""
  1342. instr = {}
  1343. instr['isRaster'] = True
  1344. try:
  1345. map = text.split()[1]
  1346. except IndexError:
  1347. GError(_("Failed to read instruction %s") % instruction)
  1348. return False
  1349. try:
  1350. info = grass.find_file(map, element = 'cell')
  1351. except grass.ScriptError, e:
  1352. GError(message = e.value)
  1353. return False
  1354. instr['raster'] = info['fullname']
  1355. self.instruction.update(instr)
  1356. return True
  1357. class Vector(InstructionObject):
  1358. """!Class keeps vector layers"""
  1359. def __init__(self, id):
  1360. InstructionObject.__init__(self, id = id)
  1361. self.type = 'vector'
  1362. # default values
  1363. self.defaultInstruction = dict(list = None)# [vmap, type, id, lpos, label]
  1364. # current values
  1365. self.instruction = dict(self.defaultInstruction)
  1366. def __str__(self):
  1367. return ''
  1368. def Read(self, instruction, text, **kwargs):
  1369. """!Read instruction and save information"""
  1370. instr = {}
  1371. for line in text:
  1372. if line.startswith('vpoints') or line.startswith('vlines') or line.startswith('vareas'):
  1373. # subtype
  1374. if line.startswith('vpoints'):
  1375. subType = 'points'
  1376. elif line.startswith('vlines'):
  1377. subType = 'lines'
  1378. elif line.startswith('vareas'):
  1379. subType = 'areas'
  1380. # name of vector map
  1381. vmap = line.split()[1]
  1382. try:
  1383. info = grass.find_file(vmap, element = 'vector')
  1384. except grass.ScriptError, e:
  1385. GError(message = e.value)
  1386. return False
  1387. vmap = info['fullname']
  1388. # id
  1389. id = kwargs['id']
  1390. # lpos
  1391. lpos = kwargs['vectorMapNumber']
  1392. #label
  1393. label = '('.join(vmap.split('@')) + ')'
  1394. break
  1395. instr = [vmap, subType, id, lpos, label]
  1396. if not self.instruction['list']:
  1397. self.instruction['list'] = []
  1398. self.instruction['list'].append(instr)
  1399. return True
  1400. class VProperties(InstructionObject):
  1401. """!Class represents instructions vareas, vlines, vpoints"""
  1402. def __init__(self, id, subType):
  1403. InstructionObject.__init__(self, id = id)
  1404. self.type = 'vProperties'
  1405. self.subType = subType
  1406. # default values
  1407. if self.subType == 'points':
  1408. dd = dict(subType = 'points', name = None, type = 'point or centroid', connection = False, layer = '1',
  1409. masked = 'n', color = '0:0:0', width = 1,
  1410. fcolor = '255:0:0', rgbcolumn = None, symbol = os.path.join('basic', 'x'), eps = None,
  1411. size = 5, sizecolumn = None, scale = None,
  1412. rotation = False, rotate = 0, rotatecolumn = None, label = None, lpos = None)
  1413. elif self.subType == 'lines':
  1414. dd = dict(subType = 'lines', name = None, type = 'line or boundary', connection = False, layer = '1',
  1415. masked = 'n', color = '0:0:0', hwidth = 1,
  1416. hcolor = 'none', rgbcolumn = None,
  1417. width = 1, cwidth = None,
  1418. style = 'solid', linecap = 'butt', label = None, lpos = None)
  1419. else: # areas
  1420. dd = dict(subType = 'areas', name = None, connection = False, layer = '1',
  1421. masked = 'n', color = '0:0:0', width = 1,
  1422. fcolor = 'none', rgbcolumn = None,
  1423. pat = None, pwidth = 1, scale = 1, label = None, lpos = None)
  1424. self.defaultInstruction = dd
  1425. # current values
  1426. self.instruction = dict(self.defaultInstruction)
  1427. def __str__(self):
  1428. dic = self.instruction
  1429. vInstruction = string.Template("v$subType $name\n").substitute(dic)
  1430. #data selection
  1431. if self.subType in ('points', 'lines'):
  1432. vInstruction += string.Template(" type $type\n").substitute(dic)
  1433. if dic['connection']:
  1434. vInstruction += string.Template(" layer $layer\n").substitute(dic)
  1435. if dic.has_key('cats'):
  1436. vInstruction += string.Template(" cats $cats\n").substitute(dic)
  1437. elif dic.has_key('where'):
  1438. vInstruction += string.Template(" where $where\n").substitute(dic)
  1439. vInstruction += string.Template(" masked $masked\n").substitute(dic)
  1440. #colors
  1441. vInstruction += string.Template(" color $color\n").substitute(dic)
  1442. if self.subType in ('points', 'areas'):
  1443. if dic['color'] != 'none':
  1444. vInstruction += string.Template(" width $width\n").substitute(dic)
  1445. if dic['rgbcolumn']:
  1446. vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic)
  1447. vInstruction += string.Template(" fcolor $fcolor\n").substitute(dic)
  1448. else:
  1449. if dic['rgbcolumn']:
  1450. vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic)
  1451. elif dic['hcolor'] != 'none':
  1452. vInstruction += string.Template(" hwidth $hwidth\n").substitute(dic)
  1453. vInstruction += string.Template(" hcolor $hcolor\n").substitute(dic)
  1454. # size and style
  1455. if self.subType == 'points':
  1456. if dic['symbol']:
  1457. vInstruction += string.Template(" symbol $symbol\n").substitute(dic)
  1458. else: #eps
  1459. vInstruction += string.Template(" eps $eps\n").substitute(dic)
  1460. if dic['size']:
  1461. vInstruction += string.Template(" size $size\n").substitute(dic)
  1462. else: # sizecolumn
  1463. vInstruction += string.Template(" sizecolumn $sizecolumn\n").substitute(dic)
  1464. vInstruction += string.Template(" scale $scale\n").substitute(dic)
  1465. if dic['rotation']:
  1466. if dic['rotate'] is not None:
  1467. vInstruction += string.Template(" rotate $rotate\n").substitute(dic)
  1468. else:
  1469. vInstruction += string.Template(" rotatecolumn $rotatecolumn\n").substitute(dic)
  1470. if self.subType == 'areas':
  1471. if dic['pat'] is not None:
  1472. vInstruction += string.Template(" pat $pat\n").substitute(dic)
  1473. vInstruction += string.Template(" pwidth $pwidth\n").substitute(dic)
  1474. vInstruction += string.Template(" scale $scale\n").substitute(dic)
  1475. if self.subType == 'lines':
  1476. if dic['width'] is not None:
  1477. vInstruction += string.Template(" width $width\n").substitute(dic)
  1478. else:
  1479. vInstruction += string.Template(" cwidth $cwidth\n").substitute(dic)
  1480. vInstruction += string.Template(" style $style\n").substitute(dic)
  1481. vInstruction += string.Template(" linecap $linecap\n").substitute(dic)
  1482. #position and label in vlegend
  1483. vInstruction += string.Template(" label $label\n lpos $lpos\n").substitute(dic)
  1484. vInstruction += " end"
  1485. return vInstruction
  1486. def Read(self, instruction, text, **kwargs):
  1487. """!Read instruction and save information"""
  1488. instr = {}
  1489. try:
  1490. info = grass.find_file(name = text[0].split()[1], element = 'vector')
  1491. except grass.ScriptError, e:
  1492. GError(message = e.value)
  1493. return False
  1494. instr['name'] = info['fullname']
  1495. #connection
  1496. instr['connection'] = True
  1497. self.mapDBInfo = dbm_base.VectorDBInfo(instr['name'])
  1498. self.layers = self.mapDBInfo.layers.keys()
  1499. if not self.layers:
  1500. instr['connection'] = False
  1501. # points
  1502. if text[0].startswith('vpoints'):
  1503. for line in text[1:]:
  1504. if line.startswith('type'):
  1505. tp = []
  1506. if line.find('point') != -1:
  1507. tp.append('point')
  1508. if line.find('centroid') != -1:
  1509. tp.append('centroid')
  1510. instr['type'] = ' or '.join(tp)
  1511. elif line.startswith('fcolor'):
  1512. instr['fcolor'] = line.split()[1]
  1513. elif line.startswith('rgbcolumn'):
  1514. instr['rgbcolumn'] = line.split()[1]
  1515. elif line.startswith('symbol'):
  1516. instr['symbol'] = line.split()[1]
  1517. elif line.startswith('eps'):
  1518. instr['eps'] = line.split()[1]
  1519. elif line.startswith('size '):
  1520. instr['size'] = line.split()[1]
  1521. elif line.startswith('sizecolumn'):
  1522. instr['size'] = None
  1523. instr['sizecolumn'] = line.split()[1]
  1524. elif line.startswith('scale '):
  1525. instr['scale'] = float(line.split()[1])
  1526. elif line.startswith('rotate '):
  1527. instr['rotation'] = True
  1528. instr['rotate'] = line.split()[1]
  1529. elif line.startswith('rotatecolumn'):
  1530. instr['rotatecolumn'] = line.split()[1]
  1531. instr['rotation'] = True
  1532. instr['rotate'] = None
  1533. # lines
  1534. elif text[0].startswith('vlines'):
  1535. for line in text[1:]:
  1536. if line.startswith('type'):
  1537. tp = []
  1538. if line.find('line') != -1:
  1539. tp.append('line')
  1540. if line.find('boundary') != -1:
  1541. tp.append('boundary')
  1542. instr['type'] = ' or '.join(tp)
  1543. elif line.startswith('hwidth'):
  1544. instr['hwidth'] = float(line.split()[1])
  1545. elif line.startswith('hcolor'):
  1546. instr['hcolor'] = line.split()[1]
  1547. elif line.startswith('rgbcolumn'):
  1548. instr['rgbcolumn'] = line.split()[1]
  1549. elif line.startswith('cwidth'):
  1550. instr['cwidth'] = float(line.split()[1])
  1551. instr['width'] = None
  1552. elif line.startswith('style'):
  1553. instr['style'] = line.split()[1]
  1554. elif line.startswith('linecap'):
  1555. instr['linecap'] = line.split()[1]
  1556. elif text[0].startswith('vareas'):
  1557. for line in text[1:]:
  1558. if line.startswith('fcolor'):
  1559. instr['fcolor'] = line.split()[1]
  1560. elif line.startswith('pat'):
  1561. instr['pat'] = line.split()[1]
  1562. elif line.startswith('pwidth'):
  1563. instr['pwidth'] = float(line.split()[1])
  1564. elif line.startswith('scale'):
  1565. instr['scale'] = float(line.split()[1])
  1566. # same properties for all
  1567. for line in text[1:]:
  1568. if line.startswith('lpos'):
  1569. instr['lpos'] = int(line.split()[1])
  1570. elif line.startswith('label'):
  1571. instr['label'] = line.split(None, 1)[1]
  1572. elif line.startswith('layer'):
  1573. instr['layer'] = line.split()[1]
  1574. elif line.startswith('masked'):
  1575. if line.split()[1].lower() in ('y', 'yes'):
  1576. instr['masked'] = 'y'
  1577. else:
  1578. instr['masked'] = 'n'
  1579. elif line.startswith('color'):
  1580. instr['color'] = line.split()[1]
  1581. elif line.startswith('rgbcolumn'):
  1582. instr['rgbcolumn'] = line.split()[1]
  1583. elif line.startswith('width'):
  1584. instr['width'] = float(line.split()[1])
  1585. if 'label' not in instr:
  1586. instr['label'] = '('.join(instr['name'].split('@')) + ')'
  1587. if 'lpos' not in instr:
  1588. instr['lpos'] = kwargs['vectorMapNumber']
  1589. self.instruction.update(instr)
  1590. return True
  1591. class PsmapDialog(wx.Dialog):
  1592. def __init__(self, parent, id, title, settings, apply = True):
  1593. wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY,
  1594. title = title, size = wx.DefaultSize,
  1595. style = wx.CAPTION|wx.MINIMIZE_BOX|wx.CLOSE_BOX)
  1596. self.apply = apply
  1597. self.id = id
  1598. self.parent = parent
  1599. self.instruction = settings
  1600. self.objectType = None
  1601. self.unitConv = UnitConversion(self)
  1602. self.spinCtrlSize = (65, -1)
  1603. self.Bind(wx.EVT_CLOSE, self.OnClose)
  1604. def AddUnits(self, parent, dialogDict):
  1605. parent.units = dict()
  1606. parent.units['unitsLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Units:"))
  1607. choices = self.unitConv.getPageUnitsNames()
  1608. parent.units['unitsCtrl'] = wx.Choice(parent, id = wx.ID_ANY, choices = choices)
  1609. parent.units['unitsCtrl'].SetStringSelection(self.unitConv.findName(dialogDict['unit']))
  1610. def AddPosition(self, parent, dialogDict):
  1611. if not hasattr(parent, "position"):
  1612. parent.position = dict()
  1613. parent.position['comment'] = wx.StaticText(parent, id = wx.ID_ANY,\
  1614. label = _("Position of the top left corner\nfrom the top left edge of the paper"))
  1615. parent.position['xLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("X:"))
  1616. parent.position['yLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Y:"))
  1617. parent.position['xCtrl'] = wx.TextCtrl(parent, id = wx.ID_ANY, value = str(dialogDict['where'][0]), validator = TCValidator(flag = 'DIGIT_ONLY'))
  1618. parent.position['yCtrl'] = wx.TextCtrl(parent, id = wx.ID_ANY, value = str(dialogDict['where'][1]), validator = TCValidator(flag = 'DIGIT_ONLY'))
  1619. if dialogDict.has_key('unit'):
  1620. x = self.unitConv.convert(value = dialogDict['where'][0], fromUnit = 'inch', toUnit = dialogDict['unit'])
  1621. y = self.unitConv.convert(value = dialogDict['where'][1], fromUnit = 'inch', toUnit = dialogDict['unit'])
  1622. parent.position['xCtrl'].SetValue("%5.3f" % x)
  1623. parent.position['yCtrl'].SetValue("%5.3f" % y)
  1624. def AddExtendedPosition(self, panel, gridBagSizer, dialogDict):
  1625. """!Add widgets for setting position relative to paper and to map"""
  1626. panel.position = dict()
  1627. positionLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Position is given:"))
  1628. panel.position['toPaper'] = wx.RadioButton(panel, id = wx.ID_ANY, label = _("relatively to paper"), style = wx.RB_GROUP)
  1629. panel.position['toMap'] = wx.RadioButton(panel, id = wx.ID_ANY, label = _("by map coordinates"))
  1630. panel.position['toPaper'].SetValue(dialogDict['XY'])
  1631. panel.position['toMap'].SetValue(not dialogDict['XY'])
  1632. gridBagSizer.Add(positionLabel, pos = (0,0), span = (1,3), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT, border = 0)
  1633. gridBagSizer.Add(panel.position['toPaper'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT, border = 0)
  1634. gridBagSizer.Add(panel.position['toMap'], pos = (1,1),flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT, border = 0)
  1635. # first box - paper coordinates
  1636. box1 = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = "")
  1637. sizerP = wx.StaticBoxSizer(box1, wx.VERTICAL)
  1638. self.gridBagSizerP = wx.GridBagSizer (hgap = 5, vgap = 5)
  1639. self.gridBagSizerP.AddGrowableCol(1)
  1640. self.gridBagSizerP.AddGrowableRow(3)
  1641. self.AddPosition(parent = panel, dialogDict = dialogDict)
  1642. panel.position['comment'].SetLabel(_("Position from the top left\nedge of the paper"))
  1643. self.AddUnits(parent = panel, dialogDict = dialogDict)
  1644. self.gridBagSizerP.Add(panel.units['unitsLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1645. self.gridBagSizerP.Add(panel.units['unitsCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1646. self.gridBagSizerP.Add(panel.position['xLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1647. self.gridBagSizerP.Add(panel.position['xCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1648. self.gridBagSizerP.Add(panel.position['yLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1649. self.gridBagSizerP.Add(panel.position['yCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1650. self.gridBagSizerP.Add(panel.position['comment'], pos = (3,0), span = (1,2), flag = wx.ALIGN_BOTTOM, border = 0)
  1651. sizerP.Add(self.gridBagSizerP, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  1652. gridBagSizer.Add(sizerP, pos = (2,0),span = (1,1), flag = wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND, border = 0)
  1653. # second box - map coordinates
  1654. box2 = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = "")
  1655. sizerM = wx.StaticBoxSizer(box2, wx.VERTICAL)
  1656. self.gridBagSizerM = wx.GridBagSizer (hgap = 5, vgap = 5)
  1657. self.gridBagSizerM.AddGrowableCol(0)
  1658. self.gridBagSizerM.AddGrowableCol(1)
  1659. eastingLabel = wx.StaticText(panel, id = wx.ID_ANY, label = "E:")
  1660. northingLabel = wx.StaticText(panel, id = wx.ID_ANY, label = "N:")
  1661. panel.position['eCtrl'] = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
  1662. panel.position['nCtrl'] = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
  1663. east, north = PaperMapCoordinates(map = self.instruction[self.mapId], x = dialogDict['where'][0], y = dialogDict['where'][1], paperToMap = True)
  1664. panel.position['eCtrl'].SetValue(str(east))
  1665. panel.position['nCtrl'].SetValue(str(north))
  1666. self.gridBagSizerM.Add(eastingLabel, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1667. self.gridBagSizerM.Add(northingLabel, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1668. self.gridBagSizerM.Add(panel.position['eCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1669. self.gridBagSizerM.Add(panel.position['nCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  1670. sizerM.Add(self.gridBagSizerM, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  1671. gridBagSizer.Add(sizerM, pos = (2,1), flag = wx.ALIGN_LEFT|wx.EXPAND, border = 0)
  1672. def AddFont(self, parent, dialogDict, color = True):
  1673. parent.font = dict()
  1674. ## parent.font['fontLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose font:"))
  1675. ## parent.font['fontCtrl'] = wx.FontPickerCtrl(parent, id = wx.ID_ANY)
  1676. ##
  1677. ## parent.font['fontCtrl'].SetSelectedFont(
  1678. ## wx.FontFromNativeInfoString(dialogDict['font'] + " " + str(dialogDict['fontsize'])))
  1679. ## parent.font['fontCtrl'].SetMaxPointSize(50)
  1680. ##
  1681. ## if color:
  1682. ## parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose color:"))
  1683. ## parent.font['colorCtrl'] = wx.ColourPickerCtrl(parent, id = wx.ID_ANY, style=wx.FNTP_FONTDESC_AS_LABEL)
  1684. ## parent.font['colorCtrl'].SetColour(dialogDict['color'])
  1685. ## parent.font['colorCtrl'].SetColour(convertRGB(dialogDict['color']))
  1686. parent.font['fontLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Font:"))
  1687. parent.font['fontSizeLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Font size:"))
  1688. fontChoices = [ 'Times-Roman', 'Times-Italic', 'Times-Bold', 'Times-BoldItalic', 'Helvetica',\
  1689. 'Helvetica-Oblique', 'Helvetica-Bold', 'Helvetica-BoldOblique', 'Courier',\
  1690. 'Courier-Oblique', 'Courier-Bold', 'Courier-BoldOblique']
  1691. parent.font['fontCtrl'] = wx.Choice(parent, id = wx.ID_ANY, choices = fontChoices)
  1692. if dialogDict['font'] in fontChoices:
  1693. parent.font['fontCtrl'].SetStringSelection(dialogDict['font'])
  1694. else:
  1695. parent.font['fontCtrl'].SetStringSelection('Helvetica')
  1696. parent.font['fontSizeCtrl'] = wx.SpinCtrl(parent, id = wx.ID_ANY, min = 4, max = 50, initial = 10)
  1697. parent.font['fontSizeCtrl'].SetValue(dialogDict['fontsize'])
  1698. if color:
  1699. parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose color:"))
  1700. parent.font['colorCtrl'] = wx.ColourPickerCtrl(parent, id = wx.ID_ANY)
  1701. parent.font['colorCtrl'].SetColour(convertRGB(dialogDict['color']))
  1702. ## parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Color:"))
  1703. ## colorChoices = [ 'aqua', 'black', 'blue', 'brown', 'cyan', 'gray', 'green', 'indigo', 'magenta',\
  1704. ## 'orange', 'purple', 'red', 'violet', 'white', 'yellow']
  1705. ## parent.colorCtrl = wx.Choice(parent, id = wx.ID_ANY, choices = colorChoices)
  1706. ## parent.colorCtrl.SetStringSelection(parent.rLegendDict['color'])
  1707. ## parent.font['colorCtrl'] = wx.ColourPickerCtrl(parent, id = wx.ID_ANY)
  1708. ## parent.font['colorCtrl'].SetColour(dialogDict['color'])
  1709. def OnApply(self, event):
  1710. ok = self.update()
  1711. if ok:
  1712. self.parent.DialogDataChanged(id = self.id)
  1713. return True
  1714. else:
  1715. return False
  1716. def OnOK(self, event):
  1717. """!Apply changes, close dialog"""
  1718. ok = self.OnApply(event)
  1719. if ok:
  1720. self.Close()
  1721. def OnCancel(self, event):
  1722. """!Close dialog"""
  1723. self.Close()
  1724. def OnClose(self, event):
  1725. """!Destroy dialog and delete it from open dialogs"""
  1726. if self.objectType:
  1727. for each in self.objectType:
  1728. if each in self.parent.openDialogs:
  1729. del self.parent.openDialogs[each]
  1730. event.Skip()
  1731. self.Destroy()
  1732. def _layout(self, panel):
  1733. #buttons
  1734. btnCancel = wx.Button(self, wx.ID_CANCEL)
  1735. btnOK = wx.Button(self, wx.ID_OK)
  1736. btnOK.SetDefault()
  1737. if self.apply:
  1738. btnApply = wx.Button(self, wx.ID_APPLY)
  1739. # bindigs
  1740. btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
  1741. btnOK.SetToolTipString(_("Close dialog and apply changes"))
  1742. #btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  1743. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  1744. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  1745. if self.apply:
  1746. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  1747. btnApply.SetToolTipString(_("Apply changes"))
  1748. # sizers
  1749. btnSizer = wx.StdDialogButtonSizer()
  1750. btnSizer.AddButton(btnCancel)
  1751. if self.apply:
  1752. btnSizer.AddButton(btnApply)
  1753. btnSizer.AddButton(btnOK)
  1754. btnSizer.Realize()
  1755. mainSizer = wx.BoxSizer(wx.VERTICAL)
  1756. mainSizer.Add(item = panel, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
  1757. mainSizer.Add(item = btnSizer, proportion = 0,
  1758. flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
  1759. self.SetSizer(mainSizer)
  1760. mainSizer.Layout()
  1761. mainSizer.Fit(self)
  1762. class PageSetupDialog(PsmapDialog):
  1763. def __init__(self, parent, id, settings):
  1764. PsmapDialog.__init__(self, parent = parent, id = id, title = "Page setup", settings = settings)
  1765. self.cat = ['Units', 'Format', 'Orientation', 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
  1766. labels = [_('Units'), _('Format'), _('Orientation'), _('Width'), _('Height'),
  1767. _('Left'), _('Right'), _('Top'), _('Bottom')]
  1768. self.catsLabels = dict(zip(self.cat, labels))
  1769. paperString = RunCommand('ps.map', flags = 'p', read = True, quiet = True)
  1770. self.paperTable = self._toList(paperString)
  1771. self.unitsList = self.unitConv.getPageUnitsNames()
  1772. self.pageSetupDict = settings[id].GetInstruction()
  1773. self._layout()
  1774. if self.pageSetupDict:
  1775. self.getCtrl('Units').SetStringSelection(self.unitConv.findName(self.pageSetupDict['Units']))
  1776. if self.pageSetupDict['Format'] == 'custom':
  1777. self.getCtrl('Format').SetSelection(self.getCtrl('Format').GetCount() - 1)
  1778. else:
  1779. self.getCtrl('Format').SetStringSelection(self.pageSetupDict['Format'])
  1780. if self.pageSetupDict['Orientation'] == 'Portrait':
  1781. self.getCtrl('Orientation').SetSelection(0)
  1782. else:
  1783. self.getCtrl('Orientation').SetSelection(1)
  1784. for item in self.cat[3:]:
  1785. val = self.unitConv.convert(value = self.pageSetupDict[item],
  1786. fromUnit = 'inch', toUnit = self.pageSetupDict['Units'])
  1787. self.getCtrl(item).SetValue("%4.3f" % val)
  1788. if self.getCtrl('Format').GetSelection() != self.getCtrl('Format').GetCount() - 1: # custom
  1789. self.getCtrl('Width').Disable()
  1790. self.getCtrl('Height').Disable()
  1791. else:
  1792. self.getCtrl('Orientation').Disable()
  1793. # events
  1794. self.getCtrl('Units').Bind(wx.EVT_CHOICE, self.OnChoice)
  1795. self.getCtrl('Format').Bind(wx.EVT_CHOICE, self.OnChoice)
  1796. self.getCtrl('Orientation').Bind(wx.EVT_CHOICE, self.OnChoice)
  1797. self.btnOk.Bind(wx.EVT_BUTTON, self.OnOK)
  1798. def update(self):
  1799. self.pageSetupDict['Units'] = self.unitConv.findUnit(self.getCtrl('Units').GetStringSelection())
  1800. self.pageSetupDict['Format'] = self.paperTable[self.getCtrl('Format').GetSelection()]['Format']
  1801. if self.getCtrl('Orientation').GetSelection() == 0:
  1802. self.pageSetupDict['Orientation'] = 'Portrait'
  1803. else:
  1804. self.pageSetupDict['Orientation'] = 'Landscape'
  1805. for item in self.cat[3:]:
  1806. self.pageSetupDict[item] = self.unitConv.convert(value = float(self.getCtrl(item).GetValue()),
  1807. fromUnit = self.pageSetupDict['Units'], toUnit = 'inch')
  1808. def OnOK(self, event):
  1809. try:
  1810. self.update()
  1811. except ValueError:
  1812. wx.MessageBox(message = _("Literal is not allowed!"), caption = _('Invalid input'),
  1813. style = wx.OK|wx.ICON_ERROR)
  1814. else:
  1815. event.Skip()
  1816. def _layout(self):
  1817. size = (110,-1)
  1818. #sizers
  1819. mainSizer = wx.BoxSizer(wx.VERTICAL)
  1820. pageBox = wx.StaticBox(self, id = wx.ID_ANY, label = " %s " % _("Page size"))
  1821. pageSizer = wx.StaticBoxSizer(pageBox, wx.VERTICAL)
  1822. marginBox = wx.StaticBox(self, id = wx.ID_ANY, label = " %s " % _("Margins"))
  1823. marginSizer = wx.StaticBoxSizer(marginBox, wx.VERTICAL)
  1824. horSizer = wx.BoxSizer(wx.HORIZONTAL)
  1825. #staticText + choice
  1826. choices = [self.unitsList, [item['Format'] for item in self.paperTable], [_('Portrait'), _('Landscape')]]
  1827. propor = [0,1,1]
  1828. border = [5,3,3]
  1829. self.hBoxDict={}
  1830. for i, item in enumerate(self.cat[:3]):
  1831. hBox = wx.BoxSizer(wx.HORIZONTAL)
  1832. stText = wx.StaticText(self, id = wx.ID_ANY, label = self.catsLabels[item] + ':')
  1833. choice = wx.Choice(self, id = wx.ID_ANY, choices = choices[i], size = size)
  1834. hBox.Add(stText, proportion = propor[i], flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = border[i])
  1835. hBox.Add(choice, proportion = 0, flag = wx.ALL, border = border[i])
  1836. if item == 'Units':
  1837. hBox.Add(size,1)
  1838. self.hBoxDict[item] = hBox
  1839. #staticText + TextCtrl
  1840. for item in self.cat[3:]:
  1841. hBox = wx.BoxSizer(wx.HORIZONTAL)
  1842. label = wx.StaticText(self, id = wx.ID_ANY, label = self.catsLabels[item] + ':')
  1843. textctrl = wx.TextCtrl(self, id = wx.ID_ANY, size = size, value = '')
  1844. hBox.Add(label, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 3)
  1845. hBox.Add(textctrl, proportion = 0, flag = wx.ALIGN_CENTRE|wx.ALL, border = 3)
  1846. self.hBoxDict[item] = hBox
  1847. sizer = list([mainSizer] + [pageSizer]*4 + [marginSizer]*4)
  1848. for i, item in enumerate(self.cat):
  1849. sizer[i].Add(self.hBoxDict[item], 0, wx.GROW|wx.RIGHT|wx.LEFT,5)
  1850. # OK button
  1851. btnSizer = wx.StdDialogButtonSizer()
  1852. self.btnOk = wx.Button(self, wx.ID_OK)
  1853. self.btnOk.SetDefault()
  1854. btnSizer.AddButton(self.btnOk)
  1855. btn = wx.Button(self, wx.ID_CANCEL)
  1856. btnSizer.AddButton(btn)
  1857. btnSizer.Realize()
  1858. horSizer.Add(pageSizer, proportion = 0, flag = wx.LEFT|wx.RIGHT|wx.BOTTOM, border = 10)
  1859. horSizer.Add(marginSizer, proportion = 0, flag = wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, border = 10)
  1860. mainSizer.Add(horSizer, proportion = 0, border = 10)
  1861. mainSizer.Add(btnSizer, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, border = 10)
  1862. self.SetSizer(mainSizer)
  1863. mainSizer.Fit(self)
  1864. def OnChoice(self, event):
  1865. currPaper = self.paperTable[self.getCtrl('Format').GetSelection()]
  1866. currUnit = self.unitConv.findUnit(self.getCtrl('Units').GetStringSelection())
  1867. currOrientIdx = self.getCtrl('Orientation').GetSelection()
  1868. newSize = dict()
  1869. for item in self.cat[3:]:
  1870. newSize[item] = self.unitConv.convert(float(currPaper[item]), fromUnit = 'inch', toUnit = currUnit)
  1871. enable = True
  1872. if currPaper['Format'] != _('custom'):
  1873. if currOrientIdx == 1: # portrait
  1874. newSize['Width'], newSize['Height'] = newSize['Height'], newSize['Width']
  1875. for item in self.cat[3:]:
  1876. self.getCtrl(item).ChangeValue("%4.3f" % newSize[item])
  1877. enable = False
  1878. self.getCtrl('Width').Enable(enable)
  1879. self.getCtrl('Height').Enable(enable)
  1880. self.getCtrl('Orientation').Enable(not enable)
  1881. def getCtrl(self, item):
  1882. return self.hBoxDict[item].GetItem(1).GetWindow()
  1883. def _toList(self, paperStr):
  1884. sizeList = list()
  1885. for line in paperStr.strip().split('\n'):
  1886. d = dict(zip([self.cat[1]]+ self.cat[3:],line.split()))
  1887. sizeList.append(d)
  1888. d = {}.fromkeys([self.cat[1]]+ self.cat[3:], 100)
  1889. d.update(Format = _('custom'))
  1890. sizeList.append(d)
  1891. return sizeList
  1892. class MapDialog(PsmapDialog):
  1893. """!Dialog for map frame settings and optionally raster and vector map selection"""
  1894. def __init__(self, parent, id, settings, rect = None, notebook = False):
  1895. PsmapDialog.__init__(self, parent = parent, id = id, title = "", settings = settings)
  1896. self.isNotebook = notebook
  1897. if self.isNotebook:
  1898. self.objectType = ('mapNotebook',)
  1899. else:
  1900. self.objectType = ('map',)
  1901. #notebook
  1902. if self.isNotebook:
  1903. self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
  1904. self.mPanel = MapFramePanel(parent = self.notebook, id = self.id[0], settings = self.instruction,
  1905. rect = rect, notebook = True)
  1906. self.id[0] = self.mPanel.getId()
  1907. self.rPanel = RasterPanel(parent = self.notebook, id = self.id[1], settings = self.instruction,
  1908. notebook = True)
  1909. self.id[1] = self.rPanel.getId()
  1910. self.vPanel = VectorPanel(parent = self.notebook, id = self.id[2], settings = self.instruction,
  1911. notebook = True)
  1912. self.id[2] = self.vPanel.getId()
  1913. self._layout(self.notebook)
  1914. self.SetTitle(_("Map settings"))
  1915. else:
  1916. self.mPanel = MapFramePanel(parent = self, id = self.id[0], settings = self.instruction,
  1917. rect = rect, notebook = False)
  1918. self.id[0] = self.mPanel.getId()
  1919. self._layout(self.mPanel)
  1920. self.SetTitle(_("Map frame settings"))
  1921. def OnApply(self, event):
  1922. """!Apply changes"""
  1923. if self.isNotebook:
  1924. okV = self.vPanel.update()
  1925. okR = self.rPanel.update()
  1926. if okV and self.id[2] in self.instruction:
  1927. self.parent.DialogDataChanged(id = self.id[2])
  1928. if okR and self.id[1] in self.instruction:
  1929. self.parent.DialogDataChanged(id = self.id[1])
  1930. if not okR or not okV:
  1931. return False
  1932. ok = self.mPanel.update()
  1933. if ok:
  1934. self.parent.DialogDataChanged(id = self.id[0])
  1935. return True
  1936. return False
  1937. def OnCancel(self, event):
  1938. """!Close dialog and remove tmp red box"""
  1939. self.parent.canvas.pdcTmp.RemoveId(self.parent.canvas.idZoomBoxTmp)
  1940. self.parent.canvas.Refresh()
  1941. self.Close()
  1942. def updateDialog(self):
  1943. """!Update raster and vector information"""
  1944. if self.mPanel.scaleChoice.GetSelection() == 0:
  1945. if self.mPanel.rasterTypeRadio.GetValue():
  1946. if 'raster' in self.parent.openDialogs:
  1947. if self.parent.openDialogs['raster'].rPanel.rasterYesRadio.GetValue() and \
  1948. self.parent.openDialogs['raster'].rPanel.rasterSelect.GetValue() == self.mPanel.select.GetValue():
  1949. self.mPanel.drawMap.SetValue(True)
  1950. else:
  1951. self.mPanel.drawMap.SetValue(False)
  1952. else:
  1953. if 'vector' in self.parent.openDialogs:
  1954. found = False
  1955. for each in self.parent.openDialogs['vector'].vPanel.vectorList:
  1956. if each[0] == self.mPanel.select.GetValue():
  1957. found = True
  1958. self.mPanel.drawMap.SetValue(found)
  1959. class MapFramePanel(wx.Panel):
  1960. """!wx.Panel with map (scale, region, border) settings"""
  1961. def __init__(self, parent, id, settings, rect, notebook = True):
  1962. wx.Panel.__init__(self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
  1963. self.id = id
  1964. self.instruction = settings
  1965. if notebook:
  1966. self.book = parent
  1967. self.book.AddPage(page = self, text = _("Map frame"))
  1968. self.mapDialog = self.book.GetParent()
  1969. else:
  1970. self.mapDialog = parent
  1971. if self.id is not None:
  1972. self.mapFrameDict = self.instruction[self.id].GetInstruction()
  1973. else:
  1974. self.id = wx.NewId()
  1975. mapFrame = MapFrame(self.id)
  1976. self.mapFrameDict = mapFrame.GetInstruction()
  1977. self.mapFrameDict['rect'] = rect
  1978. self._layout()
  1979. self.scale = [None]*4
  1980. self.center = [None]*4
  1981. self.selectedMap = self.mapFrameDict['map']
  1982. self.selectedRegion = self.mapFrameDict['region']
  1983. self.scaleType = self.mapFrameDict['scaleType']
  1984. self.mapType = self.mapFrameDict['mapType']
  1985. self.scaleChoice.SetSelection(self.mapFrameDict['scaleType'])
  1986. if self.instruction[self.id]:
  1987. self.drawMap.SetValue(self.mapFrameDict['drawMap'])
  1988. else:
  1989. self.drawMap.SetValue(True)
  1990. if self.mapFrameDict['scaleType'] == 0 and self.mapFrameDict['map']:
  1991. self.select.SetValue(self.mapFrameDict['map'])
  1992. if self.mapFrameDict['mapType'] == 'raster':
  1993. self.rasterTypeRadio.SetValue(True)
  1994. self.vectorTypeRadio.SetValue(False)
  1995. else:
  1996. self.rasterTypeRadio.SetValue(False)
  1997. self.vectorTypeRadio.SetValue(True)
  1998. elif self.mapFrameDict['scaleType'] == 1 and self.mapFrameDict['region']:
  1999. self.select.SetValue(self.mapFrameDict['region'])
  2000. self.OnMap(None)
  2001. self.scale[self.mapFrameDict['scaleType']] = self.mapFrameDict['scale']
  2002. self.center[self.mapFrameDict['scaleType']] = self.mapFrameDict['center']
  2003. self.OnScaleChoice(None)
  2004. self.OnElementType(None)
  2005. self.OnBorder(None)
  2006. def _layout(self):
  2007. """!Do layout"""
  2008. border = wx.BoxSizer(wx.VERTICAL)
  2009. box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Map frame"))
  2010. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  2011. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  2012. #scale options
  2013. frameText = wx.StaticText(self, id = wx.ID_ANY, label = _("Map frame options:"))
  2014. scaleChoices = [_("fit frame to match selected map"),
  2015. _("fit frame to match saved region"),
  2016. _("fit frame to match current computational region"),
  2017. _("fixed scale and map center")]
  2018. self.scaleChoice = wx.Choice(self, id = wx.ID_ANY, choices = scaleChoices)
  2019. gridBagSizer.Add(frameText, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2020. gridBagSizer.Add(self.scaleChoice, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2021. #map and region selection
  2022. self.staticBox = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Map selection"))
  2023. sizerM = wx.StaticBoxSizer(self.staticBox, wx.HORIZONTAL)
  2024. self.mapSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  2025. self.rasterTypeRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("raster"), style = wx.RB_GROUP)
  2026. self.vectorTypeRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("vector"))
  2027. self.drawMap = wx.CheckBox(self, id = wx.ID_ANY, label = "add selected map")
  2028. self.mapOrRegionText = [_("Map:"), _("Region:")]
  2029. dc = wx.PaintDC(self)# determine size of labels
  2030. width = max(dc.GetTextExtent(self.mapOrRegionText[0])[0], dc.GetTextExtent(self.mapOrRegionText[1])[0])
  2031. self.mapText = wx.StaticText(self, id = wx.ID_ANY, label = self.mapOrRegionText[0], size = (width, -1))
  2032. self.select = Select(self, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
  2033. type = 'raster', multiple = False,
  2034. updateOnPopup = True, onPopup = None)
  2035. self.mapSizer.Add(self.rasterTypeRadio, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2036. self.mapSizer.Add(self.vectorTypeRadio, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2037. self.mapSizer.Add(self.drawMap, pos = (0, 3), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
  2038. self.mapSizer.Add(self.mapText, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2039. self.mapSizer.Add(self.select, pos = (1, 1), span = (1, 3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2040. sizerM.Add(self.mapSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2041. gridBagSizer.Add(sizerM, pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2042. #map scale and center
  2043. boxC = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Map scale and center"))
  2044. sizerC = wx.StaticBoxSizer(boxC, wx.HORIZONTAL)
  2045. self.centerSizer = wx.FlexGridSizer(rows = 2, cols = 5, hgap = 5, vgap = 5)
  2046. centerText = wx.StaticText(self, id = wx.ID_ANY, label = _("Center:"))
  2047. self.eastingText = wx.StaticText(self, id = wx.ID_ANY, label = _("E:"))
  2048. self.northingText = wx.StaticText(self, id = wx.ID_ANY, label = _("N:"))
  2049. self.eastingTextCtrl = wx.TextCtrl(self, id = wx.ID_ANY, style = wx.TE_RIGHT, validator = TCValidator(flag = 'DIGIT_ONLY'))
  2050. self.northingTextCtrl = wx.TextCtrl(self, id = wx.ID_ANY, style = wx.TE_RIGHT, validator = TCValidator(flag = 'DIGIT_ONLY'))
  2051. scaleText = wx.StaticText(self, id = wx.ID_ANY, label = _("Scale:"))
  2052. scalePrefixText = wx.StaticText(self, id = wx.ID_ANY, label = _("1 :"))
  2053. self.scaleTextCtrl = wx.TextCtrl(self, id = wx.ID_ANY, value = "", style = wx.TE_RIGHT, validator = TCValidator('DIGIT_ONLY'))
  2054. self.centerSizer.Add(centerText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border = 10)
  2055. self.centerSizer.Add(self.eastingText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
  2056. self.centerSizer.Add(self.eastingTextCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2057. self.centerSizer.Add(self.northingText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
  2058. self.centerSizer.Add(self.northingTextCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2059. self.centerSizer.Add(scaleText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border = 10)
  2060. self.centerSizer.Add(scalePrefixText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
  2061. self.centerSizer.Add(self.scaleTextCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2062. sizerC.Add(self.centerSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2063. gridBagSizer.Add(sizerC, pos = (3, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2064. #resolution
  2065. flexSizer = wx.FlexGridSizer(rows = 1, cols = 2, hgap = 5, vgap = 5)
  2066. resolutionText = wx.StaticText(self, id = wx.ID_ANY, label = _("Map max resolution (dpi):"))
  2067. self.resolutionSpin = wx.SpinCtrl(self, id = wx.ID_ANY, min = 1, max = 1000, initial = 300)
  2068. flexSizer.Add(resolutionText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2069. flexSizer.Add(self.resolutionSpin, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2070. self.resolutionSpin.SetValue(self.mapFrameDict['resolution'])
  2071. gridBagSizer.Add(flexSizer, pos = (4, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2072. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2073. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2074. # border
  2075. box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Border"))
  2076. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  2077. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  2078. self.borderCheck = wx.CheckBox(self, id = wx.ID_ANY, label = (_("draw border around map frame")))
  2079. if self.mapFrameDict['border'] == 'y':
  2080. self.borderCheck.SetValue(True)
  2081. else:
  2082. self.borderCheck.SetValue(False)
  2083. self.borderColorText = wx.StaticText(self, id = wx.ID_ANY, label = _("border color:"))
  2084. self.borderWidthText = wx.StaticText(self, id = wx.ID_ANY, label = _("border width (pts):"))
  2085. self.borderColourPicker = wx.ColourPickerCtrl(self, id = wx.ID_ANY)
  2086. self.borderWidthCtrl = wx.SpinCtrl(self, id = wx.ID_ANY, min = 1, max = 100, initial = 1)
  2087. if self.mapFrameDict['border'] == 'y':
  2088. self.borderWidthCtrl.SetValue(int(self.mapFrameDict['width']))
  2089. self.borderColourPicker.SetColour(convertRGB(self.mapFrameDict['color']))
  2090. gridBagSizer.Add(self.borderCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2091. gridBagSizer.Add(self.borderColorText, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2092. gridBagSizer.Add(self.borderWidthText, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2093. gridBagSizer.Add(self.borderColourPicker, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2094. gridBagSizer.Add(self.borderWidthCtrl, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2095. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2096. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2097. self.SetSizer(border)
  2098. self.Fit()
  2099. if projInfo()['proj'] == 'll':
  2100. self.scaleChoice.SetItems(self.scaleChoice.GetItems()[0:3])
  2101. boxC.Hide()
  2102. for each in self.centerSizer.GetChildren():
  2103. each.GetWindow().Hide()
  2104. # bindings
  2105. self.scaleChoice.Bind(wx.EVT_CHOICE, self.OnScaleChoice)
  2106. self.select.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnMap)
  2107. self.Bind(wx.EVT_RADIOBUTTON, self.OnElementType, self.vectorTypeRadio)
  2108. self.Bind(wx.EVT_RADIOBUTTON, self.OnElementType, self.rasterTypeRadio)
  2109. self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.borderCheck)
  2110. def OnMap(self, event):
  2111. """!Selected map or region changing"""
  2112. if self.select.GetValue():
  2113. self.selected = self.select.GetValue()
  2114. else:
  2115. self.selected = None
  2116. if self.scaleChoice.GetSelection() == 0:
  2117. self.selectedMap = self.selected
  2118. if self.rasterTypeRadio.GetValue():
  2119. mapType = 'raster'
  2120. else:
  2121. mapType = 'vector'
  2122. self.scale[0], self.center[0], foo = AutoAdjust(self, scaleType = 0, map = self.selected,
  2123. mapType = mapType, rect = self.mapFrameDict['rect'])
  2124. #self.center[0] = self.RegionCenter(self.RegionDict(scaleType = 0))
  2125. elif self.scaleChoice.GetSelection() == 1:
  2126. self.selectedRegion = self.selected
  2127. self.scale[1], self.center[1], foo = AutoAdjust(self, scaleType = 1, region = self.selected, rect = self.mapFrameDict['rect'])
  2128. #self.center[1] = self.RegionCenter(self.RegionDict(scaleType = 1))
  2129. elif self.scaleChoice.GetSelection() == 2:
  2130. self.scale[2], self.center[2], foo = AutoAdjust(self, scaleType = 2, rect = self.mapFrameDict['rect'])
  2131. #self.center[2] = self.RegionCenter(self.RegionDict(scaleType = 2))
  2132. else:
  2133. self.scale[3] = None
  2134. self.center[3] = None
  2135. self.OnScaleChoice(None)
  2136. def OnScaleChoice(self, event):
  2137. """!Selected scale type changing"""
  2138. scaleType = self.scaleChoice.GetSelection()
  2139. if self.scaleType != scaleType:
  2140. self.scaleType = scaleType
  2141. self.select.SetValue("")
  2142. if scaleType in (0, 1): # automatic - region from raster map, saved region
  2143. if scaleType == 0:
  2144. # set map selection
  2145. self.rasterTypeRadio.Show()
  2146. self.vectorTypeRadio.Show()
  2147. self.drawMap.Show()
  2148. self.staticBox.SetLabel(" %s " % _("Map selection"))
  2149. if self.rasterTypeRadio.GetValue():
  2150. stype = 'raster'
  2151. else:
  2152. stype = 'vector'
  2153. self.select.SetElementList(type = stype)
  2154. self.mapText.SetLabel(self.mapOrRegionText[0])
  2155. self.select.SetToolTipString(_("Region is set to match this map,\nraster or vector map must be added later"))
  2156. if scaleType == 1:
  2157. # set region selection
  2158. self.rasterTypeRadio.Hide()
  2159. self.vectorTypeRadio.Hide()
  2160. self.drawMap.Hide()
  2161. self.staticBox.SetLabel(" %s " % _("Region selection"))
  2162. stype = 'region'
  2163. self.select.SetElementList(type = stype)
  2164. self.mapText.SetLabel(self.mapOrRegionText[1])
  2165. self.select.SetToolTipString("")
  2166. for each in self.mapSizer.GetChildren():
  2167. each.GetWindow().Enable()
  2168. for each in self.centerSizer.GetChildren():
  2169. each.GetWindow().Disable()
  2170. if self.scale[scaleType]:
  2171. self.scaleTextCtrl.SetValue("%.0f" % (1/self.scale[scaleType]))
  2172. if self.center[scaleType]:
  2173. self.eastingTextCtrl.SetValue(str(self.center[scaleType][0]))
  2174. self.northingTextCtrl.SetValue(str(self.center[scaleType][1]))
  2175. elif scaleType == 2:
  2176. for each in self.mapSizer.GetChildren():
  2177. each.GetWindow().Disable()
  2178. for each in self.centerSizer.GetChildren():
  2179. each.GetWindow().Disable()
  2180. if self.scale[scaleType]:
  2181. self.scaleTextCtrl.SetValue("%.0f" % (1/self.scale[scaleType]))
  2182. if self.center[scaleType]:
  2183. self.eastingTextCtrl.SetValue(str(self.center[scaleType][0]))
  2184. self.northingTextCtrl.SetValue(str(self.center[scaleType][1]))
  2185. else: # fixed
  2186. for each in self.mapSizer.GetChildren():
  2187. each.GetWindow().Disable()
  2188. for each in self.centerSizer.GetChildren():
  2189. each.GetWindow().Enable()
  2190. if self.scale[scaleType]:
  2191. self.scaleTextCtrl.SetValue("%.0f" % (1/self.scale[scaleType]))
  2192. if self.center[scaleType]:
  2193. self.eastingTextCtrl.SetValue(str(self.center[scaleType][0]))
  2194. self.northingTextCtrl.SetValue(str(self.center[scaleType][1]))
  2195. def OnElementType(self, event):
  2196. """!Changes data in map selection tree ctrl popup"""
  2197. if self.rasterTypeRadio.GetValue():
  2198. mapType = 'raster'
  2199. else:
  2200. mapType = 'vector'
  2201. self.select.SetElementList(type = mapType)
  2202. if self.mapType != mapType and event is not None:
  2203. self.mapType = mapType
  2204. self.select.SetValue('')
  2205. self.mapType = mapType
  2206. def OnBorder(self, event):
  2207. """!Enables/disable the part relating to border of map frame"""
  2208. for each in (self.borderColorText, self.borderWidthText, self.borderColourPicker, self.borderWidthCtrl):
  2209. each.Enable(self.borderCheck.GetValue())
  2210. def getId(self):
  2211. """!Returns id of raster map"""
  2212. return self.id
  2213. def update(self):
  2214. """!Save changes"""
  2215. mapFrameDict = dict(self.mapFrameDict)
  2216. # resolution
  2217. mapFrameDict['resolution'] = self.resolutionSpin.GetValue()
  2218. #scale
  2219. scaleType = self.scaleType
  2220. mapFrameDict['scaleType'] = scaleType
  2221. if mapFrameDict['scaleType'] == 0:
  2222. if self.select.GetValue():
  2223. mapFrameDict['drawMap'] = self.drawMap.GetValue()
  2224. mapFrameDict['map'] = self.select.GetValue()
  2225. mapFrameDict['mapType'] = self.mapType
  2226. mapFrameDict['region'] = None
  2227. if mapFrameDict['drawMap']:
  2228. if mapFrameDict['mapType'] == 'raster':
  2229. mapFile = grass.find_file(mapFrameDict['map'], element = 'cell')
  2230. if mapFile['file'] == '':
  2231. GMessage("Raster %s not found" % mapFrameDict['map'])
  2232. return False
  2233. raster = self.instruction.FindInstructionByType('raster')
  2234. if raster:
  2235. raster['raster'] = mapFrameDict['map']
  2236. else:
  2237. raster = Raster(wx.NewId())
  2238. raster['raster'] = mapFrameDict['map']
  2239. raster['isRaster'] = True
  2240. self.instruction.AddInstruction(raster)
  2241. elif mapFrameDict['mapType'] == 'vector':
  2242. mapFile = grass.find_file(mapFrameDict['map'], element = 'vector')
  2243. if mapFile['file'] == '':
  2244. GMessage("Vector %s not found" % mapFrameDict['map'])
  2245. return False
  2246. vector = self.instruction.FindInstructionByType('vector')
  2247. isAdded = False
  2248. if vector:
  2249. for each in vector['list']:
  2250. if each[0] == mapFrameDict['map']:
  2251. isAdded = True
  2252. if not isAdded:
  2253. topoInfo = grass.vector_info_topo(map = mapFrameDict['map'])
  2254. if topoInfo:
  2255. if bool(topoInfo['areas']):
  2256. topoType = 'areas'
  2257. elif bool(topoInfo['lines']):
  2258. topoType = 'lines'
  2259. else:
  2260. topoType = 'points'
  2261. label = '('.join(mapFrameDict['map'].split('@')) + ')'
  2262. if not vector:
  2263. vector = Vector(wx.NewId())
  2264. vector['list'] = []
  2265. self.instruction.AddInstruction(vector)
  2266. id = wx.NewId()
  2267. vector['list'].insert(0, [mapFrameDict['map'], topoType, id, 1, label])
  2268. vProp = VProperties(id, topoType)
  2269. vProp['name'], vProp['label'], vProp['lpos'] = mapFrameDict['map'], label, 1
  2270. self.instruction.AddInstruction(vProp)
  2271. else:
  2272. return False
  2273. self.scale[0], self.center[0], self.rectAdjusted = AutoAdjust(self, scaleType = 0, map = mapFrameDict['map'],
  2274. mapType = self.mapType, rect = self.mapFrameDict['rect'])
  2275. if self.rectAdjusted:
  2276. mapFrameDict['rect'] = self.rectAdjusted
  2277. else:
  2278. mapFrameDict['rect'] = self.mapFrameDict['rect']
  2279. mapFrameDict['scale'] = self.scale[0]
  2280. mapFrameDict['center'] = self.center[0]
  2281. # set region
  2282. if self.mapType == 'raster':
  2283. RunCommand('g.region', rast = mapFrameDict['map'])
  2284. if self.mapType == 'vector':
  2285. raster = self.instruction.FindInstructionByType('raster')
  2286. if raster:
  2287. rasterId = raster.id
  2288. else:
  2289. rasterId = None
  2290. if rasterId:
  2291. RunCommand('g.region', vect = mapFrameDict['map'], rast = self.instruction[rasterId]['raster'])
  2292. else:
  2293. RunCommand('g.region', vect = mapFrameDict['map'])
  2294. else:
  2295. wx.MessageBox(message = _("No map selected!"),
  2296. caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR)
  2297. return False
  2298. elif mapFrameDict['scaleType'] == 1:
  2299. if self.select.GetValue():
  2300. mapFrameDict['drawMap'] = False
  2301. mapFrameDict['map'] = None
  2302. mapFrameDict['mapType'] = None
  2303. mapFrameDict['region'] = self.select.GetValue()
  2304. self.scale[1], self.center[1], self.rectAdjusted = AutoAdjust(self, scaleType = 1, region = mapFrameDict['region'],
  2305. rect = self.mapFrameDict['rect'])
  2306. if self.rectAdjusted:
  2307. mapFrameDict['rect'] = self.rectAdjusted
  2308. else:
  2309. mapFrameDict['rect'] = self.mapFrameDict['rect']
  2310. mapFrameDict['scale'] = self.scale[1]
  2311. mapFrameDict['center'] = self.center[1]
  2312. # set region
  2313. RunCommand('g.region', region = mapFrameDict['region'])
  2314. else:
  2315. wx.MessageBox(message = _("No region selected!"),
  2316. caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR)
  2317. return False
  2318. elif scaleType == 2:
  2319. mapFrameDict['drawMap'] = False
  2320. mapFrameDict['map'] = None
  2321. mapFrameDict['mapType'] = None
  2322. mapFrameDict['region'] = None
  2323. self.scale[2], self.center[2], self.rectAdjusted = AutoAdjust(self, scaleType = 2, rect = self.mapFrameDict['rect'])
  2324. if self.rectAdjusted:
  2325. mapFrameDict['rect'] = self.rectAdjusted
  2326. else:
  2327. mapFrameDict['rect'] = self.mapFrameDict['rect']
  2328. mapFrameDict['scale'] = self.scale[2]
  2329. mapFrameDict['center'] = self.center[2]
  2330. env = grass.gisenv()
  2331. windFilePath = os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], 'WIND')
  2332. try:
  2333. windFile = open(windFilePath, 'r').read()
  2334. region = grass.parse_key_val(windFile, sep = ':', val_type = float)
  2335. except IOError:
  2336. region = grass.region()
  2337. raster = self.instruction.FindInstructionByType('raster')
  2338. if raster:
  2339. rasterId = raster.id
  2340. else:
  2341. rasterId = None
  2342. if rasterId: # because of resolution
  2343. RunCommand('g.region', n = region['north'], s = region['south'],
  2344. e = region['east'], w = region['west'], rast = self.instruction[rasterId]['raster'])
  2345. else:
  2346. RunCommand('g.region', n = region['north'], s = region['south'],
  2347. e = region['east'], w = region['west'])
  2348. elif scaleType == 3:
  2349. mapFrameDict['drawMap'] = False
  2350. mapFrameDict['map'] = None
  2351. mapFrameDict['mapType'] = None
  2352. mapFrameDict['region'] = None
  2353. mapFrameDict['rect'] = self.mapFrameDict['rect']
  2354. try:
  2355. scaleNumber = float(self.scaleTextCtrl.GetValue())
  2356. centerE = float(self.eastingTextCtrl.GetValue())
  2357. centerN = float(self.northingTextCtrl.GetValue())
  2358. except (ValueError, SyntaxError):
  2359. wx.MessageBox(message = _("Invalid scale or map center!"),
  2360. caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR)
  2361. return False
  2362. mapFrameDict['scale'] = 1/scaleNumber
  2363. mapFrameDict['center'] = centerE, centerN
  2364. ComputeSetRegion(self, mapDict = mapFrameDict)
  2365. # check resolution
  2366. SetResolution(dpi = mapFrameDict['resolution'], width = mapFrameDict['rect'].width,
  2367. height = mapFrameDict['rect'].height)
  2368. # border
  2369. if self.borderCheck.GetValue():
  2370. mapFrameDict['border'] = 'y'
  2371. else:
  2372. mapFrameDict['border'] = 'n'
  2373. if mapFrameDict['border'] == 'y':
  2374. mapFrameDict['width'] = self.borderWidthCtrl.GetValue()
  2375. mapFrameDict['color'] = convertRGB(self.borderColourPicker.GetColour())
  2376. if self.id not in self.instruction:
  2377. mapFrame = MapFrame(self.id)
  2378. self.instruction.AddInstruction(mapFrame)
  2379. self.instruction[self.id].SetInstruction(mapFrameDict)
  2380. if self.id not in self.mapDialog.parent.objectId:
  2381. self.mapDialog.parent.objectId.insert(0, self.id)# map frame is drawn first
  2382. return True
  2383. class RasterPanel(wx.Panel):
  2384. """!Panel for raster map settings"""
  2385. def __init__(self, parent, id, settings, notebook = True):
  2386. wx.Panel.__init__(self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
  2387. self.instruction = settings
  2388. if notebook:
  2389. self.book = parent
  2390. self.book.AddPage(page = self, text = _("Raster map"))
  2391. self.mainDialog = self.book.GetParent()
  2392. else:
  2393. self.mainDialog = parent
  2394. if id:
  2395. self.id = id
  2396. self.rasterDict = self.instruction[self.id].GetInstruction()
  2397. else:
  2398. self.id = wx.NewId()
  2399. raster = Raster(self.id)
  2400. self.rasterDict = raster.GetInstruction()
  2401. self._layout()
  2402. self.OnRaster(None)
  2403. def _layout(self):
  2404. """!Do layout"""
  2405. border = wx.BoxSizer(wx.VERTICAL)
  2406. # choose raster map
  2407. box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Choose raster map"))
  2408. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  2409. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  2410. self.rasterNoRadio = wx.RadioButton(self, id = wx.ID_ANY, label = _("no raster map"), style = wx.RB_GROUP)
  2411. self.rasterYesRadio = wx.RadioButton(self, id = wx.ID_ANY, label = _("raster:"))
  2412. self.rasterSelect = Select(self, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
  2413. type = 'raster', multiple = False,
  2414. updateOnPopup = True, onPopup = None)
  2415. if self.rasterDict['isRaster']:
  2416. self.rasterYesRadio.SetValue(True)
  2417. self.rasterNoRadio.SetValue(False)
  2418. self.rasterSelect.SetValue(self.rasterDict['raster'])
  2419. else:
  2420. self.rasterYesRadio.SetValue(False)
  2421. self.rasterNoRadio.SetValue(True)
  2422. mapId = self.instruction.FindInstructionByType('map').id
  2423. if self.instruction[mapId]['map'] and self.instruction[mapId]['mapType'] == 'raster':
  2424. self.rasterSelect.SetValue(self.instruction[mapId]['map'])# raster map from map frame dialog if possible
  2425. else:
  2426. self.rasterSelect.SetValue('')
  2427. gridBagSizer.Add(self.rasterNoRadio, pos = (0, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2428. gridBagSizer.Add(self.rasterYesRadio, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2429. gridBagSizer.Add(self.rasterSelect, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2430. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2431. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2432. #self.rasterSelect.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnRaster)
  2433. self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterNoRadio)
  2434. self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterYesRadio)
  2435. self.SetSizer(border)
  2436. self.Fit()
  2437. def OnRaster(self, event):
  2438. """!Enable/disable raster selection"""
  2439. self.rasterSelect.Enable(self.rasterYesRadio.GetValue())
  2440. def update(self):
  2441. #draw raster
  2442. mapInstr = self.instruction.FindInstructionByType('map')
  2443. if not mapInstr: # no map frame
  2444. GMessage(message = _("Please, create map frame first."))
  2445. return
  2446. if self.rasterNoRadio.GetValue() or not self.rasterSelect.GetValue():
  2447. self.rasterDict['isRaster'] = False
  2448. self.rasterDict['raster'] = None
  2449. mapInstr['drawMap'] = False
  2450. if self.id in self.instruction:
  2451. del self.instruction[self.id]
  2452. else:
  2453. self.rasterDict['isRaster'] = True
  2454. self.rasterDict['raster'] = self.rasterSelect.GetValue()
  2455. if self.rasterDict['raster'] != mapInstr['drawMap']:
  2456. mapInstr['drawMap'] = False
  2457. raster = self.instruction.FindInstructionByType('raster')
  2458. if not raster:
  2459. raster = Raster(self.id)
  2460. self.instruction.AddInstruction(raster)
  2461. self.instruction[self.id].SetInstruction(self.rasterDict)
  2462. else:
  2463. self.instruction[raster.id].SetInstruction(self.rasterDict)
  2464. if 'map' in self.mainDialog.parent.openDialogs:
  2465. self.mainDialog.parent.openDialogs['map'].updateDialog()
  2466. return True
  2467. def getId(self):
  2468. return self.id
  2469. class VectorPanel(wx.Panel):
  2470. """!Panel for vector maps settings"""
  2471. def __init__(self, parent, id, settings, notebook = True):
  2472. wx.Panel.__init__(self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
  2473. self.parent = parent
  2474. self.instruction = settings
  2475. self.tmpDialogDict = {}
  2476. vectors = self.instruction.FindInstructionByType('vProperties', list = True)
  2477. for vector in vectors:
  2478. self.tmpDialogDict[vector.id] = dict(self.instruction[vector.id].GetInstruction())
  2479. if id:
  2480. self.id = id
  2481. self.vectorList = deepcopy(self.instruction[id]['list'])
  2482. else:
  2483. self.id = wx.NewId()
  2484. self.vectorList = []
  2485. vLegend = self.instruction.FindInstructionByType('vectorLegend')
  2486. if vLegend:
  2487. self.vLegendId = vLegend.id
  2488. else:
  2489. self.vLegendId = None
  2490. self._layout()
  2491. if notebook:
  2492. self.parent.AddPage(page = self, text = _("Vector maps"))
  2493. self.parent = self.parent.GetParent()
  2494. def _layout(self):
  2495. """!Do layout"""
  2496. border = wx.BoxSizer(wx.VERTICAL)
  2497. # choose vector map
  2498. box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Add map"))
  2499. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  2500. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  2501. text = wx.StaticText(self, id = wx.ID_ANY, label = _("Map:"))
  2502. self.select = Select(self, id = wx.ID_ANY,# size = globalvar.DIALOG_GSELECT_SIZE,
  2503. type = 'vector', multiple = False,
  2504. updateOnPopup = True, onPopup = None)
  2505. topologyType = [_("points"), _("lines"), _("areas")]
  2506. self.vectorType = wx.RadioBox(self, id = wx.ID_ANY, label = " %s " % _("Data Type"), choices = topologyType,
  2507. majorDimension = 3, style = wx.RA_SPECIFY_COLS)
  2508. self.AddVector = wx.Button(self, id = wx.ID_ANY, label = _("Add"))
  2509. gridBagSizer.Add(text, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2510. gridBagSizer.Add(self.select, pos = (0,1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2511. gridBagSizer.Add(self.vectorType, pos = (1,1), flag = wx.ALIGN_CENTER, border = 0)
  2512. gridBagSizer.Add(self.AddVector, pos = (1,2), flag = wx.ALIGN_BOTTOM|wx.ALIGN_RIGHT, border = 0)
  2513. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2514. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2515. # manage vector layers
  2516. box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Manage vector maps"))
  2517. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  2518. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  2519. gridBagSizer.AddGrowableCol(0,2)
  2520. gridBagSizer.AddGrowableCol(1,1)
  2521. text = wx.StaticText(self, id = wx.ID_ANY, label = _("The topmost vector map overlaps the others"))
  2522. self.listbox = wx.ListBox(self, id = wx.ID_ANY, choices = [], style = wx.LB_SINGLE|wx.LB_NEEDED_SB)
  2523. self.btnUp = wx.Button(self, id = wx.ID_ANY, label = _("Up"))
  2524. self.btnDown = wx.Button(self, id = wx.ID_ANY, label = _("Down"))
  2525. self.btnDel = wx.Button(self, id = wx.ID_ANY, label = _("Delete"))
  2526. self.btnProp = wx.Button(self, id = wx.ID_ANY, label = _("Properties..."))
  2527. self.updateListBox(selected=0)
  2528. gridBagSizer.Add(text, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2529. gridBagSizer.Add(self.listbox, pos = (1,0), span = (4, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2530. gridBagSizer.Add(self.btnUp, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2531. gridBagSizer.Add(self.btnDown, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2532. gridBagSizer.Add(self.btnDel, pos = (3,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2533. gridBagSizer.Add(self.btnProp, pos = (4,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2534. sizer.Add(gridBagSizer, proportion = 0, flag = wx.ALL, border = 5)
  2535. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2536. self.Bind(wx.EVT_BUTTON, self.OnAddVector, self.AddVector)
  2537. self.Bind(wx.EVT_BUTTON, self.OnDelete, self.btnDel)
  2538. self.Bind(wx.EVT_BUTTON, self.OnUp, self.btnUp)
  2539. self.Bind(wx.EVT_BUTTON, self.OnDown, self.btnDown)
  2540. self.Bind(wx.EVT_BUTTON, self.OnProperties, self.btnProp)
  2541. self.select.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnVector)
  2542. self.SetSizer(border)
  2543. self.Fit()
  2544. self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnProperties, self.listbox)
  2545. def OnVector(self, event):
  2546. """!Gets info about toplogy and enables/disables choices point/line/area"""
  2547. vmap = self.select.GetValue()
  2548. try:
  2549. topoInfo = grass.vector_info_topo(map = vmap)
  2550. except grass.ScriptError:
  2551. return
  2552. if topoInfo:
  2553. self.vectorType.EnableItem(2, bool(topoInfo['areas']))
  2554. self.vectorType.EnableItem(1, bool(topoInfo['boundaries']) or bool(topoInfo['lines']))
  2555. self.vectorType.EnableItem(0, bool(topoInfo['centroids'] or bool(topoInfo['points']) ))
  2556. for item in range(2,-1,-1):
  2557. if self.vectorType.IsItemEnabled(item):
  2558. self.vectorType.SetSelection(item)
  2559. break
  2560. self.AddVector.SetFocus()
  2561. def OnAddVector(self, event):
  2562. """!Adds vector map to list"""
  2563. vmap = self.select.GetValue()
  2564. if vmap:
  2565. mapname = vmap.split('@')[0]
  2566. try:
  2567. mapset = '(' + vmap.split('@')[1] + ')'
  2568. except IndexError:
  2569. mapset = ''
  2570. type = self.vectorType.GetStringSelection()
  2571. record = "%s - %s" % (vmap,type)
  2572. id = wx.NewId()
  2573. lpos = 1
  2574. label = mapname + mapset
  2575. self.vectorList.insert(0, [vmap, type, id, lpos, label])
  2576. self.reposition()
  2577. self.listbox.InsertItems([record], 0)
  2578. vector = VProperties(id, type)
  2579. self.tmpDialogDict[id] = vector.GetInstruction()
  2580. self.tmpDialogDict[id]['name'] = vmap
  2581. self.listbox.SetSelection(0)
  2582. self.listbox.EnsureVisible(0)
  2583. self.btnProp.SetFocus()
  2584. self.enableButtons()
  2585. def OnDelete(self, event):
  2586. """!Deletes vector map from the list"""
  2587. if self.listbox.GetSelections():
  2588. pos = self.listbox.GetSelection()
  2589. id = self.vectorList[pos][2]
  2590. del self.vectorList[pos]
  2591. del self.tmpDialogDict[id]
  2592. for i in range(pos, len(self.vectorList)):
  2593. if self.vectorList[i][3]:# can be 0
  2594. self.vectorList[i][3] -= 1
  2595. if pos < len(self.vectorList) -1:
  2596. selected = pos
  2597. else:
  2598. selected = len(self.vectorList) -1
  2599. self.updateListBox(selected = selected)
  2600. if self.listbox.IsEmpty():
  2601. self.enableButtons(False)
  2602. def OnUp(self, event):
  2603. """!Moves selected map to top"""
  2604. if self.listbox.GetSelections():
  2605. pos = self.listbox.GetSelection()
  2606. if pos:
  2607. self.vectorList.insert(pos - 1, self.vectorList.pop(pos))
  2608. if not self.vLegendId:
  2609. self.reposition()
  2610. if pos > 0:
  2611. self.updateListBox(selected = (pos - 1))
  2612. else:
  2613. self.updateListBox(selected = 0)
  2614. def OnDown(self, event):
  2615. """!Moves selected map to bottom"""
  2616. if self.listbox.GetSelections():
  2617. pos = self.listbox.GetSelection()
  2618. if pos != len(self.vectorList) - 1:
  2619. self.vectorList.insert(pos + 1, self.vectorList.pop(pos))
  2620. if not self.vLegendId:
  2621. self.reposition()
  2622. if pos < len(self.vectorList) -1:
  2623. self.updateListBox(selected = (pos + 1))
  2624. else:
  2625. self.updateListBox(selected = len(self.vectorList) -1)
  2626. def OnProperties(self, event):
  2627. """!Opens vector map properties dialog"""
  2628. if self.listbox.GetSelections():
  2629. pos = self.listbox.GetSelection()
  2630. id = self.vectorList[pos][2]
  2631. dlg = VPropertiesDialog(self, id = id, settings = self.instruction,
  2632. vectors = self.vectorList, tmpSettings = self.tmpDialogDict[id])
  2633. dlg.ShowModal()
  2634. self.parent.FindWindowById(wx.ID_OK).SetFocus()
  2635. def enableButtons(self, enable = True):
  2636. """!Enable/disable up, down, properties, delete buttons"""
  2637. self.btnUp.Enable(enable)
  2638. self.btnDown.Enable(enable)
  2639. self.btnProp.Enable(enable)
  2640. self.btnDel.Enable(enable)
  2641. def updateListBox(self, selected = None):
  2642. mapList = ["%s - %s" % (item[0], item[1]) for item in self.vectorList]
  2643. self.listbox.Set(mapList)
  2644. if self.listbox.IsEmpty():
  2645. self.enableButtons(False)
  2646. else:
  2647. self.enableButtons(True)
  2648. if selected is not None:
  2649. self.listbox.SetSelection(selected)
  2650. self.listbox.EnsureVisible(selected)
  2651. def reposition(self):
  2652. """!Update position in legend, used only if there is no vlegend yet"""
  2653. for i in range(len(self.vectorList)):
  2654. if self.vectorList[i][3]:
  2655. self.vectorList[i][3] = i + 1
  2656. def getId(self):
  2657. return self.id
  2658. def update(self):
  2659. vectors = self.instruction.FindInstructionByType('vProperties', list = True)
  2660. for vector in vectors:
  2661. del self.instruction[vector.id]
  2662. if self.id in self.instruction:
  2663. del self.instruction[self.id]
  2664. if len(self.vectorList) > 0:
  2665. vector = Vector(self.id)
  2666. self.instruction.AddInstruction(vector)
  2667. vector.SetInstruction({'list': deepcopy(self.vectorList)})
  2668. # save new vectors
  2669. for item in self.vectorList:
  2670. id = item[2]
  2671. vLayer = VProperties(id, item[1])
  2672. self.instruction.AddInstruction(vLayer)
  2673. vLayer.SetInstruction(self.tmpDialogDict[id])
  2674. vLayer['name'] = item[0]
  2675. vLayer['label'] = item[4]
  2676. vLayer['lpos'] = item[3]
  2677. else:
  2678. if self.id in self.instruction:
  2679. del self.instruction[self.id]
  2680. if 'map' in self.parent.parent.openDialogs:
  2681. self.parent.parent.openDialogs['map'].updateDialog()
  2682. return True
  2683. class RasterDialog(PsmapDialog):
  2684. def __init__(self, parent, id, settings):
  2685. PsmapDialog.__init__(self, parent = parent, id = id, title = _("Raster map settings"), settings = settings)
  2686. self.objectType = ('raster',)
  2687. self.rPanel = RasterPanel(parent = self, id = self.id, settings = self.instruction, notebook = False)
  2688. self.id = self.rPanel.getId()
  2689. self._layout(self.rPanel)
  2690. def update(self):
  2691. ok = self.rPanel.update()
  2692. if ok:
  2693. return True
  2694. return False
  2695. def OnApply(self, event):
  2696. ok = self.update()
  2697. if not ok:
  2698. return False
  2699. if self.id in self.instruction:
  2700. self.parent.DialogDataChanged(id = self.id)
  2701. else:
  2702. mapId = self.instruction.FindInstructionByType('map').id
  2703. self.parent.DialogDataChanged(id = mapId)
  2704. return True
  2705. def updateDialog(self):
  2706. """!Update information (not used)"""
  2707. pass
  2708. ## if 'map' in self.parent.openDialogs:
  2709. ## if self.parent.openDialogs['map'].mPanel.rasterTypeRadio.GetValue()\
  2710. ## and self.parent.openDialogs['map'].mPanel.select.GetValue():
  2711. ## if self.parent.openDialogs['map'].mPanel.drawMap.IsChecked():
  2712. ## self.rPanel.rasterSelect.SetValue(self.parent.openDialogs['map'].mPanel.select.GetValue())
  2713. class MainVectorDialog(PsmapDialog):
  2714. def __init__(self, parent, id, settings):
  2715. PsmapDialog.__init__(self, parent = parent, id = id, title = _("Vector maps settings"), settings = settings)
  2716. self.objectType = ('vector',)
  2717. self.vPanel = VectorPanel(parent = self, id = self.id, settings = self.instruction, notebook = False)
  2718. self.id = self.vPanel.getId()
  2719. self._layout(self.vPanel)
  2720. def update(self):
  2721. self.vPanel.update()
  2722. def OnApply(self, event):
  2723. self.update()
  2724. if self.id in self.instruction:
  2725. self.parent.DialogDataChanged(id = self.id)
  2726. else:
  2727. mapId = self.instruction.FindInstructionByType('map').id
  2728. self.parent.DialogDataChanged(id = mapId)
  2729. return True
  2730. def updateDialog(self):
  2731. """!Update information (not used)"""
  2732. pass
  2733. class VPropertiesDialog(PsmapDialog):
  2734. def __init__(self, parent, id, settings, vectors, tmpSettings):
  2735. PsmapDialog.__init__(self, parent = parent, id = id, title = "", settings = settings, apply = False)
  2736. vectorList = vectors
  2737. self.vPropertiesDict = tmpSettings
  2738. # determine map and its type
  2739. for item in vectorList:
  2740. if id == item[2]:
  2741. self.vectorName = item[0]
  2742. self.type = item[1]
  2743. self.SetTitle(self.vectorName + " "+ _("properties"))
  2744. #vector map info
  2745. self.connection = True
  2746. try:
  2747. self.mapDBInfo = dbm_base.VectorDBInfo(self.vectorName)
  2748. self.layers = self.mapDBInfo.layers.keys()
  2749. except grass.ScriptError:
  2750. self.connection = False
  2751. self.layers = []
  2752. if not self.layers:
  2753. self.connection = False
  2754. self.layers = []
  2755. self.currLayer = self.vPropertiesDict['layer']
  2756. #path to symbols, patterns
  2757. gisbase = os.getenv("GISBASE")
  2758. self.symbolPath = os.path.join(gisbase, 'etc', 'symbol')
  2759. self.symbols = []
  2760. for dir in os.listdir(self.symbolPath):
  2761. for symbol in os.listdir(os.path.join(self.symbolPath, dir)):
  2762. self.symbols.append(os.path.join(dir, symbol))
  2763. self.patternPath = os.path.join(gisbase, 'etc', 'paint', 'patterns')
  2764. #notebook
  2765. notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
  2766. self.DSpanel = self._DataSelectionPanel(notebook)
  2767. self.EnableLayerSelection(enable = self.connection)
  2768. selectPanel = { 'points': [self._ColorsPointAreaPanel, self._StylePointPanel],
  2769. 'lines': [self._ColorsLinePanel, self._StyleLinePanel],
  2770. 'areas': [self._ColorsPointAreaPanel, self._StyleAreaPanel]}
  2771. self.ColorsPanel = selectPanel[self.type][0](notebook)
  2772. self.OnOutline(None)
  2773. if self.type in ('points', 'areas'):
  2774. self.OnFill(None)
  2775. self.OnColor(None)
  2776. self.StylePanel = selectPanel[self.type][1](notebook)
  2777. if self.type == 'points':
  2778. self.OnSize(None)
  2779. self.OnRotation(None)
  2780. if self.type == 'areas':
  2781. self.OnPattern(None)
  2782. self._layout(notebook)
  2783. def _DataSelectionPanel(self, notebook):
  2784. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
  2785. notebook.AddPage(page = panel, text = _("Data selection"))
  2786. border = wx.BoxSizer(wx.VERTICAL)
  2787. # data type
  2788. self.checkType1 = self.checkType2 = None
  2789. if self.type in ('lines', 'points'):
  2790. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Feature type"))
  2791. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  2792. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  2793. if self.type == 'points':
  2794. label = (_("points"), _("centroids"))
  2795. else:
  2796. label = (_("lines"), _("boundaries"))
  2797. if self.type == 'points':
  2798. name = ("point", "centroid")
  2799. else:
  2800. name = ("line", "boundary")
  2801. self.checkType1 = wx.CheckBox(panel, id = wx.ID_ANY, label = label[0], name = name[0])
  2802. self.checkType2 = wx.CheckBox(panel, id = wx.ID_ANY, label = label[1], name = name[1])
  2803. self.checkType1.SetValue(self.vPropertiesDict['type'].find(name[0]) >= 0)
  2804. self.checkType2.SetValue(self.vPropertiesDict['type'].find(name[1]) >= 0)
  2805. gridBagSizer.Add(self.checkType1, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2806. gridBagSizer.Add(self.checkType2, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2807. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2808. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2809. # layer selection
  2810. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Layer selection"))
  2811. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  2812. self.gridBagSizerL = wx.GridBagSizer(hgap = 5, vgap = 5)
  2813. self.warning = wx.StaticText(panel, id = wx.ID_ANY, label = "")
  2814. if not self.connection:
  2815. self.warning = wx.StaticText(panel, id = wx.ID_ANY, label = _("Database connection is not defined in DB file."))
  2816. text = wx.StaticText(panel, id = wx.ID_ANY, label = _("Select layer:"))
  2817. self.layerChoice = wx.Choice(panel, id = wx.ID_ANY, choices = map(str, self.layers), size = self.spinCtrlSize)
  2818. self.layerChoice.SetStringSelection(self.currLayer)
  2819. if self.connection:
  2820. table = self.mapDBInfo.layers[int(self.currLayer)]['table']
  2821. else:
  2822. table = ""
  2823. self.radioWhere = wx.RadioButton(panel, id = wx.ID_ANY, label = "SELECT * FROM %s WHERE" % table, style = wx.RB_GROUP)
  2824. self.textCtrlWhere = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
  2825. if self.connection:
  2826. cols = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[int(self.currLayer)]['table'])
  2827. else:
  2828. cols = []
  2829. self.choiceColumns = wx.Choice(panel, id = wx.ID_ANY, choices = cols)
  2830. self.radioCats = wx.RadioButton(panel, id = wx.ID_ANY, label = "Choose categories ")
  2831. self.textCtrlCats = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
  2832. self.textCtrlCats.SetToolTipString(_("list of categories (e.g. 1,3,5-7)"))
  2833. if self.vPropertiesDict.has_key('cats'):
  2834. self.radioCats.SetValue(True)
  2835. self.textCtrlCats.SetValue(self.vPropertiesDict['cats'])
  2836. if self.vPropertiesDict.has_key('where'):
  2837. self.radioWhere.SetValue(True)
  2838. where = self.vPropertiesDict['where'].strip().split(" ",1)
  2839. self.choiceColumns.SetStringSelection(where[0])
  2840. self.textCtrlWhere.SetValue(where[1])
  2841. row = 0
  2842. if not self.connection:
  2843. self.gridBagSizerL.Add(self.warning, pos = (0,0), span = (1,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2844. row = 1
  2845. self.gridBagSizerL.Add(text, pos = (0 + row,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2846. self.gridBagSizerL.Add(self.layerChoice, pos = (0 + row,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2847. self.gridBagSizerL.Add(self.radioWhere, pos = (1 + row,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2848. self.gridBagSizerL.Add(self.choiceColumns, pos = (1 + row,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2849. self.gridBagSizerL.Add(self.textCtrlWhere, pos = (1 + row,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2850. self.gridBagSizerL.Add(self.radioCats, pos = (2 + row,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2851. self.gridBagSizerL.Add(self.textCtrlCats, pos = (2 + row,1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2852. sizer.Add(self.gridBagSizerL, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2853. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2854. #mask
  2855. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Mask"))
  2856. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  2857. self.mask = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Use current mask"))
  2858. if self.vPropertiesDict['masked'] == 'y':
  2859. self.mask.SetValue(True)
  2860. else:
  2861. self.mask.SetValue(False)
  2862. sizer.Add(self.mask, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2863. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2864. self.Bind(wx.EVT_CHOICE, self.OnLayer, self.layerChoice)
  2865. panel.SetSizer(border)
  2866. panel.Fit()
  2867. return panel
  2868. def _ColorsPointAreaPanel(self, notebook):
  2869. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
  2870. notebook.AddPage(page = panel, text = _("Colors"))
  2871. border = wx.BoxSizer(wx.VERTICAL)
  2872. #colors - outline
  2873. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Outline"))
  2874. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  2875. self.gridBagSizerO = wx.GridBagSizer(hgap = 5, vgap = 2)
  2876. self.outlineCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw outline"))
  2877. self.outlineCheck.SetValue(self.vPropertiesDict['color'] != 'none')
  2878. widthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):"))
  2879. if fs:
  2880. self.widthSpin = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 30,
  2881. increment = 0.5, value = 1, style = fs.FS_RIGHT)
  2882. self.widthSpin.SetFormat("%f")
  2883. self.widthSpin.SetDigits(2)
  2884. else:
  2885. self.widthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1,
  2886. size = self.spinCtrlSize)
  2887. if self.vPropertiesDict['color'] == None:
  2888. self.vPropertiesDict['color'] = 'none'
  2889. if self.vPropertiesDict['color'] != 'none':
  2890. self.widthSpin.SetValue(self.vPropertiesDict['width'] )
  2891. else:
  2892. self.widthSpin.SetValue(1)
  2893. colorText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Color:"))
  2894. self.colorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
  2895. if self.vPropertiesDict['color'] != 'none':
  2896. self.colorPicker.SetColour(convertRGB(self.vPropertiesDict['color']))
  2897. else:
  2898. self.colorPicker.SetColour(convertRGB('black'))
  2899. self.gridBagSizerO.Add(self.outlineCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2900. self.gridBagSizerO.Add(widthText, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2901. self.gridBagSizerO.Add(self.widthSpin, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2902. self.gridBagSizerO.Add(colorText, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2903. self.gridBagSizerO.Add(self.colorPicker, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2904. sizer.Add(self.gridBagSizerO, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2905. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2906. self.Bind(wx.EVT_CHECKBOX, self.OnOutline, self.outlineCheck)
  2907. #colors - fill
  2908. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Fill"))
  2909. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  2910. self.gridBagSizerF = wx.GridBagSizer(hgap = 5, vgap = 2)
  2911. self.fillCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("fill color"))
  2912. self.fillCheck.SetValue(self.vPropertiesDict['fcolor'] != 'none' or self.vPropertiesDict['rgbcolumn'] is not None)
  2913. self.colorPickerRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("choose color:"), style = wx.RB_GROUP)
  2914. #set choose color option if there is no db connection
  2915. if self.connection:
  2916. self.colorPickerRadio.SetValue(not self.vPropertiesDict['rgbcolumn'])
  2917. else:
  2918. self.colorPickerRadio.SetValue(False)
  2919. self.fillColorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
  2920. if self.vPropertiesDict['fcolor'] != 'none':
  2921. self.fillColorPicker.SetColour(convertRGB(self.vPropertiesDict['fcolor']))
  2922. else:
  2923. self.fillColorPicker.SetColour(convertRGB('red'))
  2924. self.colorColRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("color from map table column:"))
  2925. self.colorColChoice = self.getColsChoice(parent = panel)
  2926. if self.connection:
  2927. if self.vPropertiesDict['rgbcolumn']:
  2928. self.colorColRadio.SetValue(True)
  2929. self.colorColChoice.SetStringSelection(self.vPropertiesDict['rgbcolumn'])
  2930. else:
  2931. self.colorColRadio.SetValue(False)
  2932. self.colorColChoice.SetSelection(0)
  2933. self.colorColChoice.Enable(self.connection)
  2934. self.colorColRadio.Enable(self.connection)
  2935. self.gridBagSizerF.Add(self.fillCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2936. self.gridBagSizerF.Add(self.colorPickerRadio, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2937. self.gridBagSizerF.Add(self.fillColorPicker, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2938. self.gridBagSizerF.Add(self.colorColRadio, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2939. self.gridBagSizerF.Add(self.colorColChoice, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2940. sizer.Add(self.gridBagSizerF, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2941. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2942. self.Bind(wx.EVT_CHECKBOX, self.OnFill, self.fillCheck)
  2943. self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorColRadio)
  2944. self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorPickerRadio)
  2945. panel.SetSizer(border)
  2946. panel.Fit()
  2947. return panel
  2948. def _ColorsLinePanel(self, notebook):
  2949. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
  2950. notebook.AddPage(page = panel, text = _("Colors"))
  2951. border = wx.BoxSizer(wx.VERTICAL)
  2952. #colors - outline
  2953. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Outline"))
  2954. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  2955. self.gridBagSizerO = wx.GridBagSizer(hgap = 5, vgap = 2)
  2956. if self.vPropertiesDict['hcolor'] == None:
  2957. self.vPropertiesDict['hcolor'] = 'none'
  2958. if self.vPropertiesDict['color'] == None:
  2959. self.vPropertiesDict['color'] = 'none'
  2960. self.outlineCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw outline"))
  2961. self.outlineCheck.SetValue(self.vPropertiesDict['hcolor'] != 'none')
  2962. self.outlineCheck.SetToolTipString(_("No effect for fill color from table column"))
  2963. widthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):"))
  2964. if fs:
  2965. self.outWidthSpin = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 30,
  2966. increment = 0.5, value = 1, style = fs.FS_RIGHT)
  2967. self.outWidthSpin.SetFormat("%f")
  2968. self.outWidthSpin.SetDigits(1)
  2969. else:
  2970. self.outWidthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 1,
  2971. size = self.spinCtrlSize)
  2972. if self.vPropertiesDict['hcolor'] != 'none':
  2973. self.outWidthSpin.SetValue(self.vPropertiesDict['hwidth'] )
  2974. else:
  2975. self.outWidthSpin.SetValue(1)
  2976. colorText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Color:"))
  2977. self.colorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
  2978. if self.vPropertiesDict['hcolor'] != 'none':
  2979. self.colorPicker.SetColour(convertRGB(self.vPropertiesDict['hcolor']) )
  2980. else:
  2981. self.colorPicker.SetColour(convertRGB('black'))
  2982. self.gridBagSizerO.Add(self.outlineCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2983. self.gridBagSizerO.Add(widthText, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2984. self.gridBagSizerO.Add(self.outWidthSpin, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  2985. self.gridBagSizerO.Add(colorText, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2986. self.gridBagSizerO.Add(self.colorPicker, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  2987. sizer.Add(self.gridBagSizerO, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  2988. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  2989. self.Bind(wx.EVT_CHECKBOX, self.OnOutline, self.outlineCheck)
  2990. #colors - fill
  2991. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Fill"))
  2992. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  2993. self.gridBagSizerF = wx.GridBagSizer(hgap = 5, vgap = 2)
  2994. fillText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Color of lines:"))
  2995. self.colorPickerRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("choose color:"), style = wx.RB_GROUP)
  2996. #set choose color option if there is no db connection
  2997. if self.connection:
  2998. self.colorPickerRadio.SetValue(not self.vPropertiesDict['rgbcolumn'])
  2999. else:
  3000. self.colorPickerRadio.SetValue(False)
  3001. self.fillColorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
  3002. if self.vPropertiesDict['color'] != 'none':
  3003. self.fillColorPicker.SetColour(convertRGB(self.vPropertiesDict['color']) )
  3004. else:
  3005. self.fillColorPicker.SetColour(convertRGB('black'))
  3006. self.colorColRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("color from map table column:"))
  3007. self.colorColChoice = self.getColsChoice(parent = panel)
  3008. if self.connection:
  3009. if self.vPropertiesDict['rgbcolumn']:
  3010. self.colorColRadio.SetValue(True)
  3011. self.colorColChoice.SetStringSelection(self.vPropertiesDict['rgbcolumn'])
  3012. else:
  3013. self.colorColRadio.SetValue(False)
  3014. self.colorColChoice.SetSelection(0)
  3015. self.colorColChoice.Enable(self.connection)
  3016. self.colorColRadio.Enable(self.connection)
  3017. self.gridBagSizerF.Add(fillText, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3018. self.gridBagSizerF.Add(self.colorPickerRadio, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3019. self.gridBagSizerF.Add(self.fillColorPicker, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3020. self.gridBagSizerF.Add(self.colorColRadio, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3021. self.gridBagSizerF.Add(self.colorColChoice, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  3022. sizer.Add(self.gridBagSizerF, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3023. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3024. self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorColRadio)
  3025. self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorPickerRadio)
  3026. panel.SetSizer(border)
  3027. panel.Fit()
  3028. return panel
  3029. def _StylePointPanel(self, notebook):
  3030. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
  3031. notebook.AddPage(page = panel, text = _("Size and style"))
  3032. border = wx.BoxSizer(wx.VERTICAL)
  3033. #symbology
  3034. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Symbology"))
  3035. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  3036. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  3037. gridBagSizer.AddGrowableCol(1)
  3038. self.symbolRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("symbol:"), style = wx.RB_GROUP)
  3039. self.symbolRadio.SetValue(bool(self.vPropertiesDict['symbol']))
  3040. self.symbolChoice = wx.Choice(panel, id = wx.ID_ANY, choices = self.symbols)
  3041. self.epsRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("eps file:"))
  3042. self.epsRadio.SetValue(bool(self.vPropertiesDict['eps']))
  3043. self.epsFileCtrl = filebrowse.FileBrowseButton(panel, id = wx.ID_ANY, labelText = '',
  3044. buttonText = _("Browse"), toolTip = _("Type filename or click browse to choose file"),
  3045. dialogTitle = _("Choose a file"), startDirectory = '', initialValue = '',
  3046. fileMask = "Encapsulated PostScript (*.eps)|*.eps|All files (*.*)|*.*", fileMode = wx.OPEN)
  3047. if self.vPropertiesDict['symbol']:
  3048. self.symbolChoice.SetStringSelection(self.vPropertiesDict['symbol'])
  3049. self.epsFileCtrl.SetValue('')
  3050. else: #eps chosen
  3051. self.epsFileCtrl.SetValue(self.vPropertiesDict['eps'])
  3052. self.symbolChoice.SetSelection(0)
  3053. gridBagSizer.Add(self.symbolRadio, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3054. gridBagSizer.Add(self.symbolChoice, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3055. gridBagSizer.Add(self.epsRadio, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3056. gridBagSizer.Add(self.epsFileCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  3057. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3058. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3059. #size
  3060. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size"))
  3061. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  3062. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  3063. gridBagSizer.AddGrowableCol(0)
  3064. self.sizeRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("size:"), style = wx.RB_GROUP)
  3065. self.sizeSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 50, initial = 1)
  3066. self.sizecolumnRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("size from map table column:"))
  3067. self.sizeColChoice = self.getColsChoice(panel)
  3068. self.scaleText = wx.StaticText(panel, id = wx.ID_ANY, label = _("scale:"))
  3069. self.scaleSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1)
  3070. self.sizeRadio.SetValue(self.vPropertiesDict['size'] is not None)
  3071. self.sizecolumnRadio.SetValue(bool(self.vPropertiesDict['sizecolumn']))
  3072. if self.vPropertiesDict['size']:
  3073. self.sizeSpin.SetValue(self.vPropertiesDict['size'])
  3074. else: self.sizeSpin.SetValue(5)
  3075. if self.vPropertiesDict['sizecolumn']:
  3076. self.scaleSpin.SetValue(self.vPropertiesDict['scale'])
  3077. self.sizeColChoice.SetStringSelection(self.vPropertiesDict['sizecolumn'])
  3078. else:
  3079. self.scaleSpin.SetValue(1)
  3080. self.sizeColChoice.SetSelection(0)
  3081. if not self.connection:
  3082. for each in (self.sizecolumnRadio, self.sizeColChoice, self.scaleSpin, self.scaleText):
  3083. each.Disable()
  3084. gridBagSizer.Add(self.sizeRadio, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3085. gridBagSizer.Add(self.sizeSpin, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3086. gridBagSizer.Add(self.sizecolumnRadio, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3087. gridBagSizer.Add(self.sizeColChoice, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  3088. gridBagSizer.Add(self.scaleText, pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
  3089. gridBagSizer.Add(self.scaleSpin, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3090. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3091. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3092. self.Bind(wx.EVT_RADIOBUTTON, self.OnSize, self.sizeRadio)
  3093. self.Bind(wx.EVT_RADIOBUTTON, self.OnSize, self.sizecolumnRadio)
  3094. #rotation
  3095. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Rotation"))
  3096. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  3097. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  3098. gridBagSizer.AddGrowableCol(1)
  3099. self.rotateCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("rotate symbols:"))
  3100. self.rotateRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("counterclockwise in degrees:"), style = wx.RB_GROUP)
  3101. self.rotateSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 0, max = 360, initial = 0)
  3102. self.rotatecolumnRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("from map table column:"))
  3103. self.rotateColChoice = self.getColsChoice(panel)
  3104. self.rotateCheck.SetValue(self.vPropertiesDict['rotation'])
  3105. self.rotateRadio.SetValue(self.vPropertiesDict['rotate'] is not None)
  3106. self.rotatecolumnRadio.SetValue(bool(self.vPropertiesDict['rotatecolumn']))
  3107. if self.vPropertiesDict['rotate']:
  3108. self.rotateSpin.SetValue(self.vPropertiesDict['rotate'])
  3109. else:
  3110. self.rotateSpin.SetValue(0)
  3111. if self.vPropertiesDict['rotatecolumn']:
  3112. self.rotateColChoice.SetStringSelection(self.vPropertiesDict['rotatecolumn'])
  3113. else:
  3114. self.rotateColChoice.SetSelection(0)
  3115. gridBagSizer.Add(self.rotateCheck, pos = (0, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3116. gridBagSizer.Add(self.rotateRadio, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3117. gridBagSizer.Add(self.rotateSpin, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3118. gridBagSizer.Add(self.rotatecolumnRadio, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3119. gridBagSizer.Add(self.rotateColChoice, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  3120. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3121. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3122. self.Bind(wx.EVT_CHECKBOX, self.OnRotation, self.rotateCheck)
  3123. self.Bind(wx.EVT_RADIOBUTTON, self.OnRotationType, self.rotateRadio)
  3124. self.Bind(wx.EVT_RADIOBUTTON, self.OnRotationType, self.rotatecolumnRadio)
  3125. panel.SetSizer(border)
  3126. panel.Fit()
  3127. return panel
  3128. def _StyleLinePanel(self, notebook):
  3129. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
  3130. notebook.AddPage(page = panel, text = _("Size and style"))
  3131. border = wx.BoxSizer(wx.VERTICAL)
  3132. #width
  3133. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Width"))
  3134. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  3135. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  3136. widthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Set width (pts):"))
  3137. if fs:
  3138. self.widthSpin = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 30,
  3139. increment = 0.5, value = 1, style = fs.FS_RIGHT)
  3140. self.widthSpin.SetFormat("%f")
  3141. self.widthSpin.SetDigits(1)
  3142. else:
  3143. self.widthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 1)
  3144. self.cwidthCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("multiply width by category value"))
  3145. if self.vPropertiesDict['width']:
  3146. self.widthSpin.SetValue(self.vPropertiesDict['width'])
  3147. self.cwidthCheck.SetValue(False)
  3148. else:
  3149. self.widthSpin.SetValue(self.vPropertiesDict['cwidth'])
  3150. self.cwidthCheck.SetValue(True)
  3151. gridBagSizer.Add(widthText, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3152. gridBagSizer.Add(self.widthSpin, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3153. gridBagSizer.Add(self.cwidthCheck, pos = (1, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3154. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3155. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3156. #style
  3157. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Line style"))
  3158. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  3159. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  3160. styleText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Choose line style:"))
  3161. penStyles = ["solid", "dashed", "dotted", "dashdotted"]
  3162. self.styleCombo = PenStyleComboBox(panel, choices = penStyles, validator = TCValidator(flag = 'ZERO_AND_ONE_ONLY'))
  3163. ## self.styleCombo = wx.ComboBox(panel, id = wx.ID_ANY,
  3164. ## choices = ["solid", "dashed", "dotted", "dashdotted"],
  3165. ## validator = TCValidator(flag = 'ZERO_AND_ONE_ONLY'))
  3166. ## self.styleCombo.SetToolTipString(_("It's possible to enter a series of 0's and 1's too. "\
  3167. ## "The first block of repeated zeros or ones represents 'draw', "\
  3168. ## "the second block represents 'blank'. An even number of blocks "\
  3169. ## "will repeat the pattern, an odd number of blocks will alternate the pattern."))
  3170. linecapText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Choose linecap:"))
  3171. self.linecapChoice = wx.Choice(panel, id = wx.ID_ANY, choices = ["butt", "round", "extended_butt"])
  3172. self.styleCombo.SetValue(self.vPropertiesDict['style'])
  3173. self.linecapChoice.SetStringSelection(self.vPropertiesDict['linecap'])
  3174. gridBagSizer.Add(styleText, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3175. gridBagSizer.Add(self.styleCombo, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  3176. gridBagSizer.Add(linecapText, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3177. gridBagSizer.Add(self.linecapChoice, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  3178. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3179. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3180. panel.SetSizer(border)
  3181. panel.Fit()
  3182. return panel
  3183. def _StyleAreaPanel(self, notebook):
  3184. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
  3185. notebook.AddPage(page = panel, text = _("Size and style"))
  3186. border = wx.BoxSizer(wx.VERTICAL)
  3187. #pattern
  3188. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Pattern"))
  3189. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  3190. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  3191. gridBagSizer.AddGrowableCol(1)
  3192. self.patternCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("use pattern:"))
  3193. self.patFileCtrl = filebrowse.FileBrowseButton(panel, id = wx.ID_ANY, labelText = _("Choose pattern file:"),
  3194. buttonText = _("Browse"), toolTip = _("Type filename or click browse to choose file"),
  3195. dialogTitle = _("Choose a file"), startDirectory = self.patternPath, initialValue = '',
  3196. fileMask = "Encapsulated PostScript (*.eps)|*.eps|All files (*.*)|*.*", fileMode = wx.OPEN)
  3197. self.patWidthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("pattern line width (pts):"))
  3198. self.patWidthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1)
  3199. self.patScaleText = wx.StaticText(panel, id = wx.ID_ANY, label = _("pattern scale factor:"))
  3200. self.patScaleSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1)
  3201. self.patternCheck.SetValue(bool(self.vPropertiesDict['pat']))
  3202. if self.patternCheck.GetValue():
  3203. self.patFileCtrl.SetValue(self.vPropertiesDict['pat'])
  3204. self.patWidthSpin.SetValue(self.vPropertiesDict['pwidth'])
  3205. self.patScaleSpin.SetValue(self.vPropertiesDict['scale'])
  3206. gridBagSizer.Add(self.patternCheck, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3207. gridBagSizer.Add(self.patFileCtrl, pos = (1, 0), span = (1, 2),flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  3208. gridBagSizer.Add(self.patWidthText, pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3209. gridBagSizer.Add(self.patWidthSpin, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3210. gridBagSizer.Add(self.patScaleText, pos = (3, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3211. gridBagSizer.Add(self.patScaleSpin, pos = (3, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3212. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3213. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3214. self.Bind(wx.EVT_CHECKBOX, self.OnPattern, self.patternCheck)
  3215. panel.SetSizer(border)
  3216. panel.Fit()
  3217. return panel
  3218. def OnLayer(self, event):
  3219. """!Change columns on layer change """
  3220. if self.layerChoice.GetStringSelection() == self.currLayer:
  3221. return
  3222. self.currLayer = self.layerChoice.GetStringSelection()
  3223. if self.connection:
  3224. cols = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[int(self.currLayer)]['table'])
  3225. else:
  3226. cols = []
  3227. self.choiceColumns.SetItems(cols)
  3228. self.choiceColumns.SetSelection(0)
  3229. if self.type in ('points', 'lines'):
  3230. self.colorColChoice.SetItems(cols)
  3231. self.colorColChoice.SetSelection(0)
  3232. def OnOutline(self, event):
  3233. for widget in self.gridBagSizerO.GetChildren():
  3234. if widget.GetWindow() != self.outlineCheck:
  3235. widget.GetWindow().Enable(self.outlineCheck.GetValue())
  3236. def OnFill(self, event):
  3237. enable = self.fillCheck.GetValue()
  3238. self.colorColChoice.Enable(enable)
  3239. self.colorColRadio.Enable(enable)
  3240. self.fillColorPicker.Enable(enable)
  3241. self.colorPickerRadio.Enable(enable)
  3242. if enable:
  3243. self.OnColor(None)
  3244. if not self.connection:
  3245. self.colorColChoice.Disable()
  3246. self.colorColRadio.Disable()
  3247. def OnColor(self, event):
  3248. self.colorColChoice.Enable(self.colorColRadio.GetValue())
  3249. self.fillColorPicker.Enable(self.colorPickerRadio.GetValue())
  3250. def OnSize(self, event):
  3251. self.sizeSpin.Enable(self.sizeRadio.GetValue())
  3252. self.sizeColChoice.Enable(self.sizecolumnRadio.GetValue())
  3253. self.scaleText.Enable(self.sizecolumnRadio.GetValue())
  3254. self.scaleSpin.Enable(self.sizecolumnRadio.GetValue())
  3255. def OnRotation(self, event):
  3256. for each in (self.rotateRadio, self.rotatecolumnRadio, self.rotateColChoice, self.rotateSpin):
  3257. if self.rotateCheck.GetValue():
  3258. each.Enable()
  3259. self.OnRotationType(event = None)
  3260. else:
  3261. each.Disable()
  3262. def OnRotationType(self, event):
  3263. self.rotateSpin.Enable(self.rotateRadio.GetValue())
  3264. self.rotateColChoice.Enable(self.rotatecolumnRadio.GetValue())
  3265. def OnPattern(self, event):
  3266. for each in (self.patFileCtrl, self.patWidthText, self.patWidthSpin, self.patScaleText, self.patScaleSpin):
  3267. each.Enable(self.patternCheck.GetValue())
  3268. def EnableLayerSelection(self, enable = True):
  3269. for widget in self.gridBagSizerL.GetChildren():
  3270. if widget.GetWindow() != self.warning:
  3271. widget.GetWindow().Enable(enable)
  3272. def getColsChoice(self, parent):
  3273. """!Returns a wx.Choice with table columns"""
  3274. if self.connection:
  3275. cols = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[int(self.currLayer)]['table'])
  3276. else:
  3277. cols = []
  3278. choice = wx.Choice(parent = parent, id = wx.ID_ANY, choices = cols)
  3279. return choice
  3280. def update(self):
  3281. #feature type
  3282. if self.type in ('lines', 'points'):
  3283. featureType = None
  3284. if self.checkType1.GetValue():
  3285. featureType = self.checkType1.GetName()
  3286. if self.checkType2.GetValue():
  3287. featureType += " or " + self.checkType2.GetName()
  3288. elif self.checkType2.GetValue():
  3289. featureType = self.checkType2.GetName()
  3290. if featureType:
  3291. self.vPropertiesDict['type'] = featureType
  3292. # is connection
  3293. self.vPropertiesDict['connection'] = self.connection
  3294. if self.connection:
  3295. self.vPropertiesDict['layer'] = self.layerChoice.GetStringSelection()
  3296. if self.radioCats.GetValue() and not self.textCtrlCats.IsEmpty():
  3297. self.vPropertiesDict['cats'] = self.textCtrlCats.GetValue()
  3298. elif self.radioWhere.GetValue() and not self.textCtrlWhere.IsEmpty():
  3299. self.vPropertiesDict['where'] = self.choiceColumns.GetStringSelection() + " " \
  3300. + self.textCtrlWhere.GetValue()
  3301. #mask
  3302. if self.mask.GetValue():
  3303. self.vPropertiesDict['masked'] = 'y'
  3304. else:
  3305. self.vPropertiesDict['masked'] = 'n'
  3306. #colors
  3307. if self.type in ('points', 'areas'):
  3308. if self.outlineCheck.GetValue():
  3309. self.vPropertiesDict['color'] = convertRGB(self.colorPicker.GetColour())
  3310. self.vPropertiesDict['width'] = self.widthSpin.GetValue()
  3311. else:
  3312. self.vPropertiesDict['color'] = 'none'
  3313. if self.fillCheck.GetValue():
  3314. if self.colorPickerRadio.GetValue():
  3315. self.vPropertiesDict['fcolor'] = convertRGB(self.fillColorPicker.GetColour())
  3316. self.vPropertiesDict['rgbcolumn'] = None
  3317. if self.colorColRadio.GetValue():
  3318. self.vPropertiesDict['fcolor'] = 'none'# this color is taken in case of no record in rgb column
  3319. self.vPropertiesDict['rgbcolumn'] = self.colorColChoice.GetStringSelection()
  3320. else:
  3321. self.vPropertiesDict['fcolor'] = 'none'
  3322. if self.type == 'lines':
  3323. #hcolor only when no rgbcolumn
  3324. if self.outlineCheck.GetValue():# and self.fillCheck.GetValue() and self.colorColRadio.GetValue():
  3325. self.vPropertiesDict['hcolor'] = convertRGB(self.colorPicker.GetColour())
  3326. self.vPropertiesDict['hwidth'] = self.outWidthSpin.GetValue()
  3327. else:
  3328. self.vPropertiesDict['hcolor'] = 'none'
  3329. if self.colorPickerRadio.GetValue():
  3330. self.vPropertiesDict['color'] = convertRGB(self.fillColorPicker.GetColour())
  3331. self.vPropertiesDict['rgbcolumn'] = None
  3332. if self.colorColRadio.GetValue():
  3333. self.vPropertiesDict['color'] = 'none'# this color is taken in case of no record in rgb column
  3334. self.vPropertiesDict['rgbcolumn'] = self.colorColChoice.GetStringSelection()
  3335. #
  3336. #size and style
  3337. #
  3338. if self.type == 'points':
  3339. #symbols
  3340. if self.symbolRadio.GetValue():
  3341. self.vPropertiesDict['symbol'] = self.symbolChoice.GetStringSelection()
  3342. self.vPropertiesDict['eps'] = None
  3343. else:
  3344. self.vPropertiesDict['eps'] = self.epsFileCtrl.GetValue()
  3345. self.vPropertiesDict['symbol'] = None
  3346. #size
  3347. if self.sizeRadio.GetValue():
  3348. self.vPropertiesDict['size'] = self.sizeSpin.GetValue()
  3349. self.vPropertiesDict['sizecolumn'] = None
  3350. self.vPropertiesDict['scale'] = None
  3351. else:
  3352. self.vPropertiesDict['sizecolumn'] = self.sizeColChoice.GetStringSelection()
  3353. self.vPropertiesDict['scale'] = self.scaleSpin.GetValue()
  3354. self.vPropertiesDict['size'] = None
  3355. #rotation
  3356. self.vPropertiesDict['rotate'] = None
  3357. self.vPropertiesDict['rotatecolumn'] = None
  3358. self.vPropertiesDict['rotation'] = False
  3359. if self.rotateCheck.GetValue():
  3360. self.vPropertiesDict['rotation'] = True
  3361. if self.rotateRadio.GetValue():
  3362. self.vPropertiesDict['rotate'] = self.rotateSpin.GetValue()
  3363. else:
  3364. self.vPropertiesDict['rotatecolumn'] = self.rotateColChoice.GetStringSelection()
  3365. if self.type == 'areas':
  3366. #pattern
  3367. self.vPropertiesDict['pat'] = None
  3368. if self.patternCheck.GetValue() and bool(self.patFileCtrl.GetValue()):
  3369. self.vPropertiesDict['pat'] = self.patFileCtrl.GetValue()
  3370. self.vPropertiesDict['pwidth'] = self.patWidthSpin.GetValue()
  3371. self.vPropertiesDict['scale'] = self.patScaleSpin.GetValue()
  3372. if self.type == 'lines':
  3373. #width
  3374. if self.cwidthCheck.GetValue():
  3375. self.vPropertiesDict['cwidth'] = self.widthSpin.GetValue()
  3376. self.vPropertiesDict['width'] = None
  3377. else:
  3378. self.vPropertiesDict['width'] = self.widthSpin.GetValue()
  3379. self.vPropertiesDict['cwidth'] = None
  3380. #line style
  3381. if self.styleCombo.GetValue():
  3382. self.vPropertiesDict['style'] = self.styleCombo.GetValue()
  3383. else:
  3384. self.vPropertiesDict['style'] = 'solid'
  3385. self.vPropertiesDict['linecap'] = self.linecapChoice.GetStringSelection()
  3386. def OnOK(self, event):
  3387. self.update()
  3388. event.Skip()
  3389. class LegendDialog(PsmapDialog):
  3390. def __init__(self, parent, id, settings, page):
  3391. PsmapDialog.__init__(self, parent = parent, id = id, title = "Legend settings", settings = settings)
  3392. self.objectType = ('rasterLegend', 'vectorLegend')
  3393. self.instruction = settings
  3394. map = self.instruction.FindInstructionByType('map')
  3395. if map:
  3396. self.mapId = map.id
  3397. else:
  3398. self.mapId = None
  3399. vector = self.instruction.FindInstructionByType('vector')
  3400. if vector:
  3401. self.vectorId = vector.id
  3402. else:
  3403. self.vectorId = None
  3404. raster = self.instruction.FindInstructionByType('raster')
  3405. if raster:
  3406. self.rasterId = raster.id
  3407. else:
  3408. self.rasterId = None
  3409. self.pageId = self.instruction.FindInstructionByType('page').id
  3410. currPage = self.instruction[self.pageId].GetInstruction()
  3411. #raster legend
  3412. if self.id[0] is not None:
  3413. self.rasterLegend = self.instruction[self.id[0]]
  3414. self.rLegendDict = self.rasterLegend.GetInstruction()
  3415. else:
  3416. self.id[0] = wx.NewId()
  3417. self.rasterLegend = RasterLegend(self.id[0])
  3418. self.rLegendDict = self.rasterLegend.GetInstruction()
  3419. self.rLegendDict['where'] = currPage['Left'], currPage['Top']
  3420. #vector legend
  3421. if self.id[1] is not None:
  3422. self.vLegendDict = self.instruction[self.id[1]].GetInstruction()
  3423. else:
  3424. self.id[1] = wx.NewId()
  3425. vectorLegend = VectorLegend(self.id[1])
  3426. self.vLegendDict = vectorLegend.GetInstruction()
  3427. self.vLegendDict['where'] = currPage['Left'], currPage['Top']
  3428. if self.rasterId:
  3429. self.currRaster = self.instruction[self.rasterId]['raster']
  3430. else:
  3431. self.currRaster = None
  3432. #notebook
  3433. self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
  3434. self.panelRaster = self._rasterLegend(self.notebook)
  3435. self.panelVector = self._vectorLegend(self.notebook)
  3436. self.OnRaster(None)
  3437. self.OnRange(None)
  3438. self.OnIsLegend(None)
  3439. self.OnSpan(None)
  3440. self.OnBorder(None)
  3441. self._layout(self.notebook)
  3442. self.notebook.ChangeSelection(page)
  3443. self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging)
  3444. def OnPageChanging(self, event):
  3445. """!Workaround to scroll up to see the checkbox"""
  3446. wx.CallAfter(self.FindWindowByName('rasterPanel').ScrollChildIntoView,
  3447. self.FindWindowByName('showRLegend'))
  3448. wx.CallAfter(self.FindWindowByName('vectorPanel').ScrollChildIntoView,
  3449. self.FindWindowByName('showVLegend'))
  3450. def _rasterLegend(self, notebook):
  3451. panel = scrolled.ScrolledPanel(parent = notebook, id = wx.ID_ANY, size = (-1, 500), style = wx.TAB_TRAVERSAL)
  3452. panel.SetupScrolling(scroll_x = False, scroll_y = True)
  3453. panel.SetName('rasterPanel')
  3454. notebook.AddPage(page = panel, text = _("Raster legend"))
  3455. border = wx.BoxSizer(wx.VERTICAL)
  3456. # is legend
  3457. self.isRLegend = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Show raster legend"))
  3458. self.isRLegend.SetValue(self.rLegendDict['rLegend'])
  3459. self.isRLegend.SetName("showRLegend")
  3460. border.Add(item = self.isRLegend, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3461. # choose raster
  3462. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Source raster"))
  3463. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  3464. flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
  3465. flexSizer.AddGrowableCol(1)
  3466. self.rasterDefault = wx.RadioButton(panel, id = wx.ID_ANY, label = _("current raster"), style = wx.RB_GROUP)
  3467. self.rasterOther = wx.RadioButton(panel, id = wx.ID_ANY, label = _("select raster"))
  3468. self.rasterDefault.SetValue(self.rLegendDict['rasterDefault'])#
  3469. self.rasterOther.SetValue(not self.rLegendDict['rasterDefault'])#
  3470. rasterType = getRasterType(map = self.currRaster)
  3471. self.rasterCurrent = wx.StaticText(panel, id = wx.ID_ANY,
  3472. label = _("%(rast)s: type %(type)s") % { 'rast' : self.currRaster,
  3473. 'type' : rasterType })
  3474. self.rasterSelect = Select(panel, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
  3475. type = 'raster', multiple = False,
  3476. updateOnPopup = True, onPopup = None)
  3477. if not self.rLegendDict['rasterDefault']:
  3478. self.rasterSelect.SetValue(self.rLegendDict['raster'])
  3479. else:
  3480. self.rasterSelect.SetValue('')
  3481. flexSizer.Add(self.rasterDefault, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3482. flexSizer.Add(self.rasterCurrent, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border = 10)
  3483. flexSizer.Add(self.rasterOther, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3484. flexSizer.Add(self.rasterSelect, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
  3485. sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
  3486. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3487. # type of legend
  3488. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Type of legend"))
  3489. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  3490. vbox = wx.BoxSizer(wx.VERTICAL)
  3491. self.discrete = wx.RadioButton(parent = panel, id = wx.ID_ANY,
  3492. label = " %s " % _("discrete legend (categorical maps)"), style = wx.RB_GROUP)
  3493. self.continuous = wx.RadioButton(parent = panel, id = wx.ID_ANY,
  3494. label = " %s " % _("continuous color gradient legend (floating point map)"))
  3495. vbox.Add(self.discrete, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 0)
  3496. vbox.Add(self.continuous, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 0)
  3497. sizer.Add(item = vbox, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
  3498. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3499. # size, position and font
  3500. self.sizePositionFont(legendType = 'raster', parent = panel, mainSizer = border)
  3501. # advanced settings
  3502. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Advanced legend settings"))
  3503. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  3504. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  3505. # no data
  3506. self.nodata = wx.CheckBox(panel, id = wx.ID_ANY, label = _('draw "no data" box'))
  3507. if self.rLegendDict['nodata'] == 'y':
  3508. self.nodata.SetValue(True)
  3509. else:
  3510. self.nodata.SetValue(False)
  3511. #tickbar
  3512. self.ticks = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw ticks across color table"))
  3513. if self.rLegendDict['tickbar'] == 'y':
  3514. self.ticks.SetValue(True)
  3515. else:
  3516. self.ticks.SetValue(False)
  3517. # range
  3518. if self.rasterId and self.instruction[self.rasterId]['raster']:
  3519. rinfo = grass.raster_info(self.instruction[self.rasterId]['raster'])
  3520. self.minim, self.maxim = rinfo['min'], rinfo['max']
  3521. else:
  3522. self.minim, self.maxim = 0,0
  3523. self.range = wx.CheckBox(panel, id = wx.ID_ANY, label = _("range"))
  3524. self.range.SetValue(self.rLegendDict['range'])
  3525. self.minText = wx.StaticText(panel, id = wx.ID_ANY, label = "min (%s)" % self.minim)
  3526. self.maxText = wx.StaticText(panel, id = wx.ID_ANY, label = "max (%s)" % self.maxim)
  3527. self.min = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(self.rLegendDict['min']))
  3528. self.max = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(self.rLegendDict['max']))
  3529. gridBagSizer.Add(self.nodata, pos = (0,0), span = (1,5), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3530. gridBagSizer.Add(self.ticks, pos = (1,0), span = (1,5), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3531. gridBagSizer.Add(self.range, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3532. gridBagSizer.Add(self.minText, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
  3533. gridBagSizer.Add(self.min, pos = (2,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3534. gridBagSizer.Add(self.maxText, pos = (2,3), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0)
  3535. gridBagSizer.Add(self.max, pos = (2,4), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3536. sizer.Add(gridBagSizer, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3537. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3538. panel.SetSizer(border)
  3539. panel.Fit()
  3540. # bindings
  3541. self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterDefault)
  3542. self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterOther)
  3543. self.Bind(wx.EVT_CHECKBOX, self.OnIsLegend, self.isRLegend)
  3544. self.Bind(wx.EVT_RADIOBUTTON, self.OnDiscrete, self.discrete)
  3545. self.Bind(wx.EVT_RADIOBUTTON, self.OnDiscrete, self.continuous)
  3546. ## self.Bind(wx.EVT_CHECKBOX, self.OnDefaultSize, panel.defaultSize)
  3547. self.Bind(wx.EVT_CHECKBOX, self.OnRange, self.range)
  3548. self.rasterSelect.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnRaster)
  3549. return panel
  3550. def _vectorLegend(self, notebook):
  3551. panel = scrolled.ScrolledPanel(parent = notebook, id = wx.ID_ANY, size = (-1, 500), style = wx.TAB_TRAVERSAL)
  3552. panel.SetupScrolling(scroll_x = False, scroll_y = True)
  3553. panel.SetName('vectorPanel')
  3554. notebook.AddPage(page = panel, text = _("Vector legend"))
  3555. border = wx.BoxSizer(wx.VERTICAL)
  3556. # is legend
  3557. self.isVLegend = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Show vector legend"))
  3558. self.isVLegend.SetValue(self.vLegendDict['vLegend'])
  3559. self.isVLegend.SetName("showVLegend")
  3560. border.Add(item = self.isVLegend, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3561. #vector maps, their order, labels
  3562. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Source vector maps"))
  3563. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  3564. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  3565. gridBagSizer.AddGrowableCol(0,3)
  3566. gridBagSizer.AddGrowableCol(1,1)
  3567. vectorText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Choose vector maps and their order in legend"))
  3568. self.vectorListCtrl = CheckListCtrl(panel)
  3569. self.vectorListCtrl.InsertColumn(0, _("Vector map"))
  3570. self.vectorListCtrl.InsertColumn(1, _("Label"))
  3571. if self.vectorId:
  3572. vectors = sorted(self.instruction[self.vectorId]['list'], key = lambda x: x[3])
  3573. for vector in vectors:
  3574. index = self.vectorListCtrl.InsertStringItem(sys.maxint, vector[0].split('@')[0])
  3575. self.vectorListCtrl.SetStringItem(index, 1, vector[4])
  3576. self.vectorListCtrl.SetItemData(index, index)
  3577. self.vectorListCtrl.CheckItem(index, True)
  3578. if vector[3] == 0:
  3579. self.vectorListCtrl.CheckItem(index, False)
  3580. if not self.vectorId:
  3581. self.vectorListCtrl.SetColumnWidth(0, 100)
  3582. else:
  3583. self.vectorListCtrl.SetColumnWidth(0, wx.LIST_AUTOSIZE)
  3584. self.vectorListCtrl.SetColumnWidth(1, wx.LIST_AUTOSIZE)
  3585. self.btnUp = wx.Button(panel, id = wx.ID_ANY, label = _("Up"))
  3586. self.btnDown = wx.Button(panel, id = wx.ID_ANY, label = _("Down"))
  3587. self.btnLabel = wx.Button(panel, id = wx.ID_ANY, label = _("Edit label"))
  3588. gridBagSizer.Add(vectorText, pos = (0,0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3589. gridBagSizer.Add(self.vectorListCtrl, pos = (1,0), span = (3,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  3590. gridBagSizer.Add(self.btnUp, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3591. gridBagSizer.Add(self.btnDown, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3592. gridBagSizer.Add(self.btnLabel, pos = (3,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3593. sizer.Add(gridBagSizer, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  3594. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3595. # size, position and font
  3596. self.sizePositionFont(legendType = 'vector', parent = panel, mainSizer = border)
  3597. # border
  3598. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Border"))
  3599. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  3600. flexGridSizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
  3601. self.borderCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw border around legend"))
  3602. self.borderColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY, style = wx.FNTP_FONTDESC_AS_LABEL)
  3603. if self.vLegendDict['border'] == 'none':
  3604. self.borderColorCtrl.SetColour(wx.BLACK)
  3605. self.borderCheck.SetValue(False)
  3606. else:
  3607. self.borderColorCtrl.SetColour(convertRGB(self.vLegendDict['border']))
  3608. self.borderCheck.SetValue(True)
  3609. flexGridSizer.Add(self.borderCheck, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3610. flexGridSizer.Add(self.borderColorCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3611. sizer.Add(item = flexGridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
  3612. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3613. self.Bind(wx.EVT_BUTTON, self.OnUp, self.btnUp)
  3614. self.Bind(wx.EVT_BUTTON, self.OnDown, self.btnDown)
  3615. self.Bind(wx.EVT_BUTTON, self.OnEditLabel, self.btnLabel)
  3616. self.Bind(wx.EVT_CHECKBOX, self.OnIsLegend, self.isVLegend)
  3617. self.Bind(wx.EVT_CHECKBOX, self.OnSpan, panel.spanRadio)
  3618. self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.borderCheck)
  3619. self.Bind(wx.EVT_FONTPICKER_CHANGED, self.OnFont, panel.font['fontCtrl'])
  3620. panel.SetSizer(border)
  3621. panel.Fit()
  3622. return panel
  3623. def sizePositionFont(self, legendType, parent, mainSizer):
  3624. """!Insert widgets for size, position and font control"""
  3625. if legendType == 'raster':
  3626. legendDict = self.rLegendDict
  3627. else:
  3628. legendDict = self.vLegendDict
  3629. panel = parent
  3630. border = mainSizer
  3631. # size and position
  3632. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size and position"))
  3633. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  3634. #unit
  3635. self.AddUnits(parent = panel, dialogDict = legendDict)
  3636. unitBox = wx.BoxSizer(wx.HORIZONTAL)
  3637. unitBox.Add(panel.units['unitsLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border = 10)
  3638. unitBox.Add(panel.units['unitsCtrl'], proportion = 1, flag = wx.ALL, border = 5)
  3639. sizer.Add(unitBox, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3640. hBox = wx.BoxSizer(wx.HORIZONTAL)
  3641. posBox = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " %_("Position"))
  3642. posSizer = wx.StaticBoxSizer(posBox, wx.VERTICAL)
  3643. sizeBox = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size"))
  3644. sizeSizer = wx.StaticBoxSizer(sizeBox, wx.VERTICAL)
  3645. posGridBagSizer = wx.GridBagSizer(hgap = 10, vgap = 5)
  3646. posGridBagSizer.AddGrowableRow(2)
  3647. #position
  3648. self.AddPosition(parent = panel, dialogDict = legendDict)
  3649. posGridBagSizer.Add(panel.position['xLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3650. posGridBagSizer.Add(panel.position['xCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3651. posGridBagSizer.Add(panel.position['yLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3652. posGridBagSizer.Add(panel.position['yCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3653. posGridBagSizer.Add(panel.position['comment'], pos = (2,0), span = (1,2), flag =wx.ALIGN_BOTTOM, border = 0)
  3654. posSizer.Add(posGridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3655. #size
  3656. width = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width:"))
  3657. if legendDict['width']:
  3658. w = self.unitConv.convert(value = float(legendDict['width']), fromUnit = 'inch', toUnit = legendDict['unit'])
  3659. else:
  3660. w = ''
  3661. panel.widthCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(w), validator = TCValidator("DIGIT_ONLY"))
  3662. panel.widthCtrl.SetToolTipString(_("Leave the edit field empty, to use default values."))
  3663. if legendType == 'raster':
  3664. ## panel.defaultSize = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Use default size"))
  3665. ## panel.defaultSize.SetValue(legendDict['defaultSize'])
  3666. panel.heightOrColumnsLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Height:"))
  3667. if legendDict['height']:
  3668. h = self.unitConv.convert(value = float(legendDict['height']), fromUnit = 'inch', toUnit = legendDict['unit'])
  3669. else:
  3670. h = ''
  3671. panel.heightOrColumnsCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(h), validator = TCValidator("DIGIT_ONLY"))
  3672. self.rSizeGBSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  3673. ## self.rSizeGBSizer.Add(panel.defaultSize, pos = (0,0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3674. self.rSizeGBSizer.Add(width, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3675. self.rSizeGBSizer.Add(panel.widthCtrl, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3676. self.rSizeGBSizer.Add(panel.heightOrColumnsLabel, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3677. self.rSizeGBSizer.Add(panel.heightOrColumnsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3678. sizeSizer.Add(self.rSizeGBSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3679. if legendType == 'vector':
  3680. panel.widthCtrl.SetToolTipString(_("Width of the color symbol (for lines)\nin front of the legend text"))
  3681. #columns
  3682. minVect, maxVect = 0, 0
  3683. if self.vectorId:
  3684. minVect = 1
  3685. maxVect = min(10, len(self.instruction[self.vectorId]['list']))
  3686. cols = wx.StaticText(panel, id = wx.ID_ANY, label = _("Columns:"))
  3687. panel.colsCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, value = "",
  3688. min = minVect, max = maxVect, initial = legendDict['cols'])
  3689. #span
  3690. panel.spanRadio = wx.CheckBox(panel, id = wx.ID_ANY, label = _("column span:"))
  3691. panel.spanTextCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = '')
  3692. panel.spanTextCtrl.SetToolTipString(_("Column separation distance between the left edges\n"\
  3693. "of two columns in a multicolumn legend"))
  3694. if legendDict['span']:
  3695. panel.spanRadio.SetValue(True)
  3696. s = self.unitConv.convert(value = float(legendDict['span']), fromUnit = 'inch', toUnit = legendDict['unit'])
  3697. panel.spanTextCtrl.SetValue(str(s))
  3698. else:
  3699. panel.spanRadio.SetValue(False)
  3700. self.vSizeGBSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  3701. self.vSizeGBSizer.AddGrowableCol(1)
  3702. self.vSizeGBSizer.Add(width, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3703. self.vSizeGBSizer.Add(panel.widthCtrl, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3704. self.vSizeGBSizer.Add(cols, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3705. self.vSizeGBSizer.Add(panel.colsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3706. self.vSizeGBSizer.Add(panel.spanRadio, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3707. self.vSizeGBSizer.Add(panel.spanTextCtrl, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3708. sizeSizer.Add(self.vSizeGBSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  3709. hBox.Add(posSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 3)
  3710. hBox.Add(sizeSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 3)
  3711. sizer.Add(hBox, proportion = 0, flag = wx.EXPAND, border = 0)
  3712. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3713. # font
  3714. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Font settings"))
  3715. fontSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  3716. flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
  3717. flexSizer.AddGrowableCol(1)
  3718. if legendType == 'raster':
  3719. self.AddFont(parent = panel, dialogDict = legendDict, color = True)
  3720. else:
  3721. self.AddFont(parent = panel, dialogDict = legendDict, color = False)
  3722. flexSizer.Add(panel.font['fontLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3723. flexSizer.Add(panel.font['fontCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3724. flexSizer.Add(panel.font['fontSizeLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3725. flexSizer.Add(panel.font['fontSizeCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3726. if legendType == 'raster':
  3727. flexSizer.Add(panel.font['colorLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3728. flexSizer.Add(panel.font['colorCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3729. fontSizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
  3730. border.Add(item = fontSizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  3731. # some enable/disable methods
  3732. def OnIsLegend(self, event):
  3733. """!Enables and disables controls, it depends if raster or vector legend is checked"""
  3734. page = self.notebook.GetSelection()
  3735. if page == 0 or event is None:
  3736. children = self.panelRaster.GetChildren()
  3737. if self.isRLegend.GetValue():
  3738. for i,widget in enumerate(children):
  3739. widget.Enable()
  3740. self.OnRaster(None)
  3741. self.OnRange(None)
  3742. self.OnDiscrete(None)
  3743. else:
  3744. for widget in children:
  3745. if widget.GetName() != 'showRLegend':
  3746. widget.Disable()
  3747. if page == 1 or event is None:
  3748. children = self.panelVector.GetChildren()
  3749. if self.isVLegend.GetValue():
  3750. for i, widget in enumerate(children):
  3751. widget.Enable()
  3752. self.OnSpan(None)
  3753. self.OnBorder(None)
  3754. else:
  3755. for widget in children:
  3756. if widget.GetName() != 'showVLegend':
  3757. widget.Disable()
  3758. def OnRaster(self, event):
  3759. if self.rasterDefault.GetValue():#default
  3760. self.rasterSelect.Disable()
  3761. type = getRasterType(self.currRaster)
  3762. else:#select raster
  3763. self.rasterSelect.Enable()
  3764. map = self.rasterSelect.GetValue()
  3765. type = getRasterType(map)
  3766. if type == 'CELL':
  3767. self.discrete.SetValue(True)
  3768. elif type in ('FCELL', 'DCELL'):
  3769. self.continuous.SetValue(True)
  3770. if event is None:
  3771. if self.rLegendDict['discrete'] == 'y':
  3772. self.discrete.SetValue(True)
  3773. elif self.rLegendDict['discrete'] == 'n':
  3774. self.continuous.SetValue(True)
  3775. self.OnDiscrete(None)
  3776. def OnDiscrete(self, event):
  3777. """! Change control according to the type of legend"""
  3778. enabledSize = self.panelRaster.heightOrColumnsCtrl.IsEnabled()
  3779. self.panelRaster.heightOrColumnsCtrl.Destroy()
  3780. if self.discrete.GetValue():
  3781. self.panelRaster.heightOrColumnsLabel.SetLabel(_("Columns:"))
  3782. self.panelRaster.heightOrColumnsCtrl = wx.SpinCtrl(self.panelRaster, id = wx.ID_ANY, value = "", min = 1, max = 10, initial = self.rLegendDict['cols'])
  3783. self.panelRaster.heightOrColumnsCtrl.Enable(enabledSize)
  3784. self.nodata.Enable()
  3785. self.range.Disable()
  3786. self.min.Disable()
  3787. self.max.Disable()
  3788. self.minText.Disable()
  3789. self.maxText.Disable()
  3790. self.ticks.Disable()
  3791. else:
  3792. self.panelRaster.heightOrColumnsLabel.SetLabel(_("Height:"))
  3793. if self.rLegendDict['height']:
  3794. h = self.unitConv.convert(value = float(self.rLegendDict['height']), fromUnit = 'inch', toUnit = self.rLegendDict['unit'])
  3795. else:
  3796. h = ''
  3797. self.panelRaster.heightOrColumnsCtrl = wx.TextCtrl(self.panelRaster, id = wx.ID_ANY,
  3798. value = str(h), validator = TCValidator("DIGIT_ONLY"))
  3799. self.panelRaster.heightOrColumnsCtrl.Enable(enabledSize)
  3800. self.nodata.Disable()
  3801. self.range.Enable()
  3802. if self.range.GetValue():
  3803. self.minText.Enable()
  3804. self.maxText.Enable()
  3805. self.min.Enable()
  3806. self.max.Enable()
  3807. self.ticks.Enable()
  3808. self.rSizeGBSizer.Add(self.panelRaster.heightOrColumnsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  3809. self.panelRaster.Layout()
  3810. self.panelRaster.Fit()
  3811. def OnRange(self, event):
  3812. if not self.range.GetValue():
  3813. self.min.Disable()
  3814. self.max.Disable()
  3815. self.minText.Disable()
  3816. self.maxText.Disable()
  3817. else:
  3818. self.min.Enable()
  3819. self.max.Enable()
  3820. self.minText.Enable()
  3821. self.maxText.Enable()
  3822. def OnUp(self, event):
  3823. """!Moves selected map up, changes order in vector legend"""
  3824. if self.vectorListCtrl.GetFirstSelected() != -1:
  3825. pos = self.vectorListCtrl.GetFirstSelected()
  3826. if pos:
  3827. idx1 = self.vectorListCtrl.GetItemData(pos) - 1
  3828. idx2 = self.vectorListCtrl.GetItemData(pos - 1) + 1
  3829. self.vectorListCtrl.SetItemData(pos, idx1)
  3830. self.vectorListCtrl.SetItemData(pos - 1, idx2)
  3831. self.vectorListCtrl.SortItems(cmp)
  3832. if pos > 0:
  3833. selected = (pos - 1)
  3834. else:
  3835. selected = 0
  3836. self.vectorListCtrl.Select(selected)
  3837. def OnDown(self, event):
  3838. """!Moves selected map down, changes order in vector legend"""
  3839. if self.vectorListCtrl.GetFirstSelected() != -1:
  3840. pos = self.vectorListCtrl.GetFirstSelected()
  3841. if pos != self.vectorListCtrl.GetItemCount() - 1:
  3842. idx1 = self.vectorListCtrl.GetItemData(pos) + 1
  3843. idx2 = self.vectorListCtrl.GetItemData(pos + 1) - 1
  3844. self.vectorListCtrl.SetItemData(pos, idx1)
  3845. self.vectorListCtrl.SetItemData(pos + 1, idx2)
  3846. self.vectorListCtrl.SortItems(cmp)
  3847. if pos < self.vectorListCtrl.GetItemCount() -1:
  3848. selected = (pos + 1)
  3849. else:
  3850. selected = self.vectorListCtrl.GetItemCount() -1
  3851. self.vectorListCtrl.Select(selected)
  3852. def OnEditLabel(self, event):
  3853. """!Change legend label of vector map"""
  3854. if self.vectorListCtrl.GetFirstSelected() != -1:
  3855. idx = self.vectorListCtrl.GetFirstSelected()
  3856. default = self.vectorListCtrl.GetItem(idx, 1).GetText()
  3857. dlg = wx.TextEntryDialog(self, message = _("Edit legend label:"), caption = _("Edit label"),
  3858. defaultValue = default, style = wx.OK|wx.CANCEL|wx.CENTRE)
  3859. if dlg.ShowModal() == wx.ID_OK:
  3860. new = dlg.GetValue()
  3861. self.vectorListCtrl.SetStringItem(idx, 1, new)
  3862. dlg.Destroy()
  3863. def OnSpan(self, event):
  3864. self.panelVector.spanTextCtrl.Enable(self.panelVector.spanRadio.GetValue())
  3865. def OnFont(self, event):
  3866. """!Changes default width according to fontsize, width [inch] = fontsize[pt]/24"""
  3867. ## fontsize = self.panelVector.font['fontCtrl'].GetSelectedFont().GetPointSize()
  3868. fontsize = self.panelVector.font['fontSizeCtrl'].GetValue()
  3869. unit = self.unitConv.findUnit(self.panelVector.units['unitsCtrl'].GetStringSelection())
  3870. w = fontsize/24.
  3871. width = self.unitConv.convert(value = w, fromUnit = 'inch', toUnit = unit)
  3872. self.panelVector.widthCtrl.SetValue("%3.2f" % width)
  3873. def OnBorder(self, event):
  3874. """!Enables/disables colorPickerCtrl for border"""
  3875. self.borderColorCtrl.Enable(self.borderCheck.GetValue())
  3876. def updateRasterLegend(self):
  3877. """!Save information from raster legend dialog to dictionary"""
  3878. #is raster legend
  3879. if not self.isRLegend.GetValue():
  3880. self.rLegendDict['rLegend'] = False
  3881. else:
  3882. self.rLegendDict['rLegend'] = True
  3883. #units
  3884. currUnit = self.unitConv.findUnit(self.panelRaster.units['unitsCtrl'].GetStringSelection())
  3885. self.rLegendDict['unit'] = currUnit
  3886. # raster
  3887. if self.rasterDefault.GetValue():
  3888. self.rLegendDict['rasterDefault'] = True
  3889. self.rLegendDict['raster'] = self.currRaster
  3890. else:
  3891. self.rLegendDict['rasterDefault'] = False
  3892. self.rLegendDict['raster'] = self.rasterSelect.GetValue()
  3893. if self.rLegendDict['rLegend'] and not self.rLegendDict['raster']:
  3894. wx.MessageBox(message = _("No raster map selected!"),
  3895. caption = _('No raster'), style = wx.OK|wx.ICON_ERROR)
  3896. return False
  3897. if self.rLegendDict['raster']:
  3898. # type and range of map
  3899. rasterType = getRasterType(self.rLegendDict['raster'])
  3900. if rasterType is None:
  3901. return False
  3902. self.rLegendDict['type'] = rasterType
  3903. #discrete
  3904. if self.discrete.GetValue():
  3905. self.rLegendDict['discrete'] = 'y'
  3906. else:
  3907. self.rLegendDict['discrete'] = 'n'
  3908. # font
  3909. self.rLegendDict['font'] = self.panelRaster.font['fontCtrl'].GetStringSelection()
  3910. self.rLegendDict['fontsize'] = self.panelRaster.font['fontSizeCtrl'].GetValue()
  3911. color = self.panelRaster.font['colorCtrl'].GetColour()
  3912. self.rLegendDict['color'] = convertRGB(color)
  3913. # position
  3914. x = self.unitConv.convert(value = float(self.panelRaster.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
  3915. y = self.unitConv.convert(value = float(self.panelRaster.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
  3916. self.rLegendDict['where'] = (x, y)
  3917. # estimated size
  3918. width = self.panelRaster.widthCtrl.GetValue()
  3919. try:
  3920. width = float(width)
  3921. width = self.unitConv.convert(value = width, fromUnit = currUnit, toUnit = 'inch')
  3922. except ValueError:
  3923. width = None
  3924. self.rLegendDict['width'] = width
  3925. if self.rLegendDict['discrete'] == 'n':
  3926. height = self.panelRaster.heightOrColumnsCtrl.GetValue()
  3927. try:
  3928. height = float(height)
  3929. height = self.unitConv.convert(value = height, fromUnit = currUnit, toUnit = 'inch')
  3930. except ValueError:
  3931. height = None
  3932. self.rLegendDict['height'] = height
  3933. else:
  3934. cols = self.panelRaster.heightOrColumnsCtrl.GetValue()
  3935. self.rLegendDict['cols'] = cols
  3936. drawHeight = self.rasterLegend.EstimateHeight(raster = self.rLegendDict['raster'], discrete = self.rLegendDict['discrete'],
  3937. fontsize = self.rLegendDict['fontsize'], cols = self.rLegendDict['cols'],
  3938. height = self.rLegendDict['height'])
  3939. drawWidth = self.rasterLegend.EstimateWidth(raster = self.rLegendDict['raster'], discrete = self.rLegendDict['discrete'],
  3940. fontsize = self.rLegendDict['fontsize'], cols = self.rLegendDict['cols'],
  3941. width = self.rLegendDict['width'], paperInstr = self.instruction[self.pageId])
  3942. self.rLegendDict['rect'] = wx.Rect2D(x = x, y = y, w = drawWidth, h = drawHeight)
  3943. # no data
  3944. if self.rLegendDict['discrete'] == 'y':
  3945. if self.nodata.GetValue():
  3946. self.rLegendDict['nodata'] = 'y'
  3947. else:
  3948. self.rLegendDict['nodata'] = 'n'
  3949. # tickbar
  3950. elif self.rLegendDict['discrete'] == 'n':
  3951. if self.ticks.GetValue():
  3952. self.rLegendDict['tickbar'] = 'y'
  3953. else:
  3954. self.rLegendDict['tickbar'] = 'n'
  3955. # range
  3956. if self.range.GetValue():
  3957. self.rLegendDict['range'] = True
  3958. self.rLegendDict['min'] = self.min.GetValue()
  3959. self.rLegendDict['max'] = self.max.GetValue()
  3960. else:
  3961. self.rLegendDict['range'] = False
  3962. if not self.id[0] in self.instruction:
  3963. rasterLegend = RasterLegend(self.id[0])
  3964. self.instruction.AddInstruction(rasterLegend)
  3965. self.instruction[self.id[0]].SetInstruction(self.rLegendDict)
  3966. if self.id[0] not in self.parent.objectId:
  3967. self.parent.objectId.append(self.id[0])
  3968. return True
  3969. def updateVectorLegend(self):
  3970. """!Save information from vector legend dialog to dictionary"""
  3971. vector = self.instruction.FindInstructionByType('vector')
  3972. if vector:
  3973. self.vectorId = vector.id
  3974. else:
  3975. self.vectorId = None
  3976. #is vector legend
  3977. if not self.isVLegend.GetValue():
  3978. self.vLegendDict['vLegend'] = False
  3979. else:
  3980. self.vLegendDict['vLegend'] = True
  3981. if self.vLegendDict['vLegend'] == True and self.vectorId is not None:
  3982. # labels
  3983. #reindex order
  3984. idx = 1
  3985. for item in range(self.vectorListCtrl.GetItemCount()):
  3986. if self.vectorListCtrl.IsChecked(item):
  3987. self.vectorListCtrl.SetItemData(item, idx)
  3988. idx += 1
  3989. else:
  3990. self.vectorListCtrl.SetItemData(item, 0)
  3991. if idx == 1:
  3992. self.vLegendDict['vLegend'] = False
  3993. else:
  3994. vList = self.instruction[self.vectorId]['list']
  3995. for i, vector in enumerate(vList):
  3996. item = self.vectorListCtrl.FindItem(start = -1, str = vector[0].split('@')[0])
  3997. vList[i][3] = self.vectorListCtrl.GetItemData(item)
  3998. vList[i][4] = self.vectorListCtrl.GetItem(item, 1).GetText()
  3999. vmaps = self.instruction.FindInstructionByType('vProperties', list = True)
  4000. for vmap, vector in zip(vmaps, vList):
  4001. self.instruction[vmap.id]['lpos'] = vector[3]
  4002. self.instruction[vmap.id]['label'] = vector[4]
  4003. #units
  4004. currUnit = self.unitConv.findUnit(self.panelVector.units['unitsCtrl'].GetStringSelection())
  4005. self.vLegendDict['unit'] = currUnit
  4006. # position
  4007. x = self.unitConv.convert(value = float(self.panelVector.position['xCtrl'].GetValue()),
  4008. fromUnit = currUnit, toUnit = 'inch')
  4009. y = self.unitConv.convert(value = float(self.panelVector.position['yCtrl'].GetValue()),
  4010. fromUnit = currUnit, toUnit = 'inch')
  4011. self.vLegendDict['where'] = (x, y)
  4012. # font
  4013. self.vLegendDict['font'] = self.panelVector.font['fontCtrl'].GetStringSelection()
  4014. self.vLegendDict['fontsize'] = self.panelVector.font['fontSizeCtrl'].GetValue()
  4015. dc = wx.PaintDC(self)
  4016. font = dc.GetFont()
  4017. dc.SetFont(wx.Font(pointSize = self.vLegendDict['fontsize'], family = font.GetFamily(),
  4018. style = font.GetStyle(), weight = wx.FONTWEIGHT_NORMAL))
  4019. #size
  4020. width = self.unitConv.convert(value = float(self.panelVector.widthCtrl.GetValue()),
  4021. fromUnit = currUnit, toUnit = 'inch')
  4022. self.vLegendDict['width'] = width
  4023. self.vLegendDict['cols'] = self.panelVector.colsCtrl.GetValue()
  4024. if self.panelVector.spanRadio.GetValue() and self.panelVector.spanTextCtrl.GetValue():
  4025. self.vLegendDict['span'] = self.panelVector.spanTextCtrl.GetValue()
  4026. else:
  4027. self.vLegendDict['span'] = None
  4028. # size estimation
  4029. vectors = self.instruction[self.vectorId]['list']
  4030. labels = [vector[4] for vector in vectors if vector[3] != 0]
  4031. extent = dc.GetTextExtent(max(labels, key = len))
  4032. wExtent = self.unitConv.convert(value = extent[0], fromUnit = 'pixel', toUnit = 'inch')
  4033. hExtent = self.unitConv.convert(value = extent[1], fromUnit = 'pixel', toUnit = 'inch')
  4034. w = (width + wExtent) * self.vLegendDict['cols']
  4035. h = len(labels) * hExtent / self.vLegendDict['cols']
  4036. h *= 1.1
  4037. self.vLegendDict['rect'] = wx.Rect2D(x, y, w, h)
  4038. #border
  4039. if self.borderCheck.GetValue():
  4040. color = self.borderColorCtrl.GetColour()
  4041. self.vLegendDict['border'] = convertRGB(color)
  4042. else:
  4043. self.vLegendDict['border'] = 'none'
  4044. if not self.id[1] in self.instruction:
  4045. vectorLegend = VectorLegend(self.id[1])
  4046. self.instruction.AddInstruction(vectorLegend)
  4047. self.instruction[self.id[1]].SetInstruction(self.vLegendDict)
  4048. if self.id[1] not in self.parent.objectId:
  4049. self.parent.objectId.append(self.id[1])
  4050. return True
  4051. def update(self):
  4052. okR = self.updateRasterLegend()
  4053. okV = self.updateVectorLegend()
  4054. if okR and okV:
  4055. return True
  4056. return False
  4057. def updateDialog(self):
  4058. """!Update legend coordinates after moving"""
  4059. # raster legend
  4060. if 'rect' in self.rLegendDict:
  4061. x, y = self.rLegendDict['rect'][:2]
  4062. currUnit = self.unitConv.findUnit(self.panelRaster.units['unitsCtrl'].GetStringSelection())
  4063. x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit)
  4064. y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit)
  4065. self.panelRaster.position['xCtrl'].SetValue("%5.3f" % x)
  4066. self.panelRaster.position['yCtrl'].SetValue("%5.3f" % y)
  4067. #update name and type of raster
  4068. raster = self.instruction.FindInstructionByType('raster')
  4069. if raster:
  4070. self.rasterId = raster.id
  4071. else:
  4072. self.rasterId = None
  4073. if raster:
  4074. currRaster = raster['raster']
  4075. else:
  4076. currRaster = None
  4077. rasterType = getRasterType(map = currRaster)
  4078. self.rasterCurrent.SetLabel(_("%(rast)s: type %(type)s") % \
  4079. { 'rast' : currRaster, 'type' : str(rasterType) })
  4080. # vector legend
  4081. if 'rect' in self.vLegendDict:
  4082. x, y = self.vLegendDict['rect'][:2]
  4083. currUnit = self.unitConv.findUnit(self.panelVector.units['unitsCtrl'].GetStringSelection())
  4084. x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit)
  4085. y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit)
  4086. self.panelVector.position['xCtrl'].SetValue("%5.3f" % x)
  4087. self.panelVector.position['yCtrl'].SetValue("%5.3f" % y)
  4088. # update vector maps
  4089. if self.instruction.FindInstructionByType('vector'):
  4090. vectors = sorted(self.instruction.FindInstructionByType('vector')['list'], key = lambda x: x[3])
  4091. self.vectorListCtrl.DeleteAllItems()
  4092. for vector in vectors:
  4093. index = self.vectorListCtrl.InsertStringItem(sys.maxint, vector[0].split('@')[0])
  4094. self.vectorListCtrl.SetStringItem(index, 1, vector[4])
  4095. self.vectorListCtrl.SetItemData(index, index)
  4096. self.vectorListCtrl.CheckItem(index, True)
  4097. if vector[3] == 0:
  4098. self.vectorListCtrl.CheckItem(index, False)
  4099. self.panelVector.colsCtrl.SetRange(1, min(10, len(self.instruction.FindInstructionByType('vector')['list'])))
  4100. self.panelVector.colsCtrl.SetValue(1)
  4101. else:
  4102. self.vectorListCtrl.DeleteAllItems()
  4103. self.panelVector.colsCtrl.SetRange(0,0)
  4104. self.panelVector.colsCtrl.SetValue(0)
  4105. class MapinfoDialog(PsmapDialog):
  4106. def __init__(self, parent, id, settings):
  4107. PsmapDialog.__init__(self, parent = parent, id = id, title = "Mapinfo settings", settings = settings)
  4108. self.objectType = ('mapinfo',)
  4109. if self.id is not None:
  4110. self.mapinfo = self.instruction[self.id]
  4111. self.mapinfoDict = self.mapinfo.GetInstruction()
  4112. else:
  4113. self.id = wx.NewId()
  4114. self.mapinfo = Mapinfo(self.id)
  4115. self.mapinfoDict = self.mapinfo.GetInstruction()
  4116. page = self.instruction.FindInstructionByType('page').GetInstruction()
  4117. self.mapinfoDict['where'] = page['Left'], page['Top']
  4118. self.panel = self._mapinfoPanel()
  4119. self._layout(self.panel)
  4120. self.OnIsBackground(None)
  4121. self.OnIsBorder(None)
  4122. def _mapinfoPanel(self):
  4123. panel = wx.Panel(parent = self, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
  4124. #panel.SetupScrolling(scroll_x = False, scroll_y = True)
  4125. border = wx.BoxSizer(wx.VERTICAL)
  4126. # position
  4127. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position"))
  4128. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4129. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  4130. gridBagSizer.AddGrowableCol(1)
  4131. self.AddPosition(parent = panel, dialogDict = self.mapinfoDict)
  4132. self.AddUnits(parent = panel, dialogDict = self.mapinfoDict)
  4133. gridBagSizer.Add(panel.units['unitsLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4134. gridBagSizer.Add(panel.units['unitsCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4135. gridBagSizer.Add(panel.position['xLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4136. gridBagSizer.Add(panel.position['xCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4137. gridBagSizer.Add(panel.position['yLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4138. gridBagSizer.Add(panel.position['yCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4139. gridBagSizer.Add(panel.position['comment'], pos = (3,0), span = (1,2), flag =wx.ALIGN_BOTTOM, border = 0)
  4140. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  4141. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4142. # font
  4143. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Font settings"))
  4144. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4145. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  4146. gridBagSizer.AddGrowableCol(1)
  4147. self.AddFont(parent = panel, dialogDict = self.mapinfoDict)#creates font color too, used below
  4148. gridBagSizer.Add(panel.font['fontLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4149. gridBagSizer.Add(panel.font['fontCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4150. gridBagSizer.Add(panel.font['fontSizeLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4151. gridBagSizer.Add(panel.font['fontSizeCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4152. gridBagSizer.Add(panel.font['colorLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4153. gridBagSizer.Add(panel.font['colorCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4154. sizer.Add(item = gridBagSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
  4155. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4156. # colors
  4157. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " %_("Color settings"))
  4158. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4159. flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
  4160. flexSizer.AddGrowableCol(1)
  4161. self.colors = {}
  4162. self.colors['borderCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("use border color:"))
  4163. self.colors['backgroundCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("use background color:"))
  4164. self.colors['borderColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
  4165. self.colors['backgroundColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
  4166. if self.mapinfoDict['border'] == None:
  4167. self.mapinfoDict['border'] = 'none'
  4168. if self.mapinfoDict['border'] != 'none':
  4169. self.colors['borderCtrl'].SetValue(True)
  4170. self.colors['borderColor'].SetColour(convertRGB(self.mapinfoDict['border']))
  4171. else:
  4172. self.colors['borderCtrl'].SetValue(False)
  4173. self.colors['borderColor'].SetColour(convertRGB('black'))
  4174. if self.mapinfoDict['background'] == None:
  4175. self.mapinfoDict['background'] == 'none'
  4176. if self.mapinfoDict['background'] != 'none':
  4177. self.colors['backgroundCtrl'].SetValue(True)
  4178. self.colors['backgroundColor'].SetColour(convertRGB(self.mapinfoDict['background']))
  4179. else:
  4180. self.colors['backgroundCtrl'].SetValue(False)
  4181. self.colors['backgroundColor'].SetColour(convertRGB('white'))
  4182. flexSizer.Add(self.colors['borderCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4183. flexSizer.Add(self.colors['borderColor'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4184. flexSizer.Add(self.colors['backgroundCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4185. flexSizer.Add(self.colors['backgroundColor'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4186. sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
  4187. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4188. panel.SetSizer(border)
  4189. self.Bind(wx.EVT_CHECKBOX, self.OnIsBorder, self.colors['borderCtrl'])
  4190. self.Bind(wx.EVT_CHECKBOX, self.OnIsBackground, self.colors['backgroundCtrl'])
  4191. return panel
  4192. def OnIsBackground(self, event):
  4193. if self.colors['backgroundCtrl'].GetValue():
  4194. self.colors['backgroundColor'].Enable()
  4195. self.update()
  4196. else:
  4197. self.colors['backgroundColor'].Disable()
  4198. def OnIsBorder(self, event):
  4199. if self.colors['borderCtrl'].GetValue():
  4200. self.colors['borderColor'].Enable()
  4201. self.update()
  4202. else:
  4203. self.colors['borderColor'].Disable()
  4204. def update(self):
  4205. #units
  4206. currUnit = self.unitConv.findUnit(self.panel.units['unitsCtrl'].GetStringSelection())
  4207. self.mapinfoDict['unit'] = currUnit
  4208. # position
  4209. if self.panel.position['xCtrl'].GetValue():
  4210. x = self.panel.position['xCtrl'].GetValue()
  4211. else:
  4212. x = self.mapinfoDict['where'][0]
  4213. if self.panel.position['yCtrl'].GetValue():
  4214. y = self.panel.position['yCtrl'].GetValue()
  4215. else:
  4216. y = self.mapinfoDict['where'][1]
  4217. x = self.unitConv.convert(value = float(self.panel.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
  4218. y = self.unitConv.convert(value = float(self.panel.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
  4219. self.mapinfoDict['where'] = (x, y)
  4220. # font
  4221. self.mapinfoDict['font'] = self.panel.font['fontCtrl'].GetStringSelection()
  4222. self.mapinfoDict['fontsize'] = self.panel.font['fontSizeCtrl'].GetValue()
  4223. #colors
  4224. color = self.panel.font['colorCtrl'].GetColour()
  4225. self.mapinfoDict['color'] = convertRGB(color)
  4226. if self.colors['backgroundCtrl'].GetValue():
  4227. background = self.colors['backgroundColor'].GetColour()
  4228. self.mapinfoDict['background'] = convertRGB(background)
  4229. else:
  4230. self.mapinfoDict['background'] = 'none'
  4231. if self.colors['borderCtrl'].GetValue():
  4232. border = self.colors['borderColor'].GetColour()
  4233. self.mapinfoDict['border'] = convertRGB(border)
  4234. else:
  4235. self.mapinfoDict['border'] = 'none'
  4236. # estimation of size
  4237. self.mapinfoDict['rect'] = self.mapinfo.EstimateRect(self.mapinfoDict)
  4238. if self.id not in self.instruction:
  4239. mapinfo = Mapinfo(self.id)
  4240. self.instruction.AddInstruction(mapinfo)
  4241. self.instruction[self.id].SetInstruction(self.mapinfoDict)
  4242. if self.id not in self.parent.objectId:
  4243. self.parent.objectId.append(self.id)
  4244. self.updateDialog()
  4245. return True
  4246. def updateDialog(self):
  4247. """!Update mapinfo coordinates, after moving"""
  4248. x, y = self.mapinfoDict['where']
  4249. currUnit = self.unitConv.findUnit(self.panel.units['unitsCtrl'].GetStringSelection())
  4250. x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit)
  4251. y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit)
  4252. self.panel.position['xCtrl'].SetValue("%5.3f" % x)
  4253. self.panel.position['yCtrl'].SetValue("%5.3f" % y)
  4254. class ScalebarDialog(PsmapDialog):
  4255. """!Dialog for scale bar"""
  4256. def __init__(self, parent, id, settings):
  4257. PsmapDialog.__init__(self, parent = parent, id = id, title = "Scale bar settings", settings = settings)
  4258. self.objectType = ('scalebar',)
  4259. if self.id is not None:
  4260. self.scalebar = self.instruction[id]
  4261. self.scalebarDict = self.scalebar.GetInstruction()
  4262. else:
  4263. self.id = wx.NewId()
  4264. self.scalebar = Scalebar(self.id)
  4265. self.scalebarDict = self.scalebar.GetInstruction()
  4266. page = self.instruction.FindInstructionByType('page').GetInstruction()
  4267. self.scalebarDict['where'] = page['Left'], page['Top']
  4268. self.panel = self._scalebarPanel()
  4269. self._layout(self.panel)
  4270. self.mapUnit = projInfo()['units'].lower()
  4271. if projInfo()['proj'] == 'xy':
  4272. self.mapUnit = 'meters'
  4273. if self.mapUnit not in self.unitConv.getAllUnits():
  4274. wx.MessageBox(message = _("Units of current projection are not supported,\n meters will be used!"),
  4275. caption = _('Unsupported units'),
  4276. style = wx.OK|wx.ICON_ERROR)
  4277. self.mapUnit = 'meters'
  4278. def _scalebarPanel(self):
  4279. panel = wx.Panel(parent = self, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
  4280. border = wx.BoxSizer(wx.VERTICAL)
  4281. #
  4282. # position
  4283. #
  4284. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position"))
  4285. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4286. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  4287. gridBagSizer.AddGrowableCol(1)
  4288. self.AddUnits(parent = panel, dialogDict = self.scalebarDict)
  4289. self.AddPosition(parent = panel, dialogDict = self.scalebarDict)
  4290. if self.scalebarDict['rect']: # set position, ref point is center and not left top corner
  4291. x = self.unitConv.convert(value = self.scalebarDict['where'][0] - self.scalebarDict['rect'].Get()[2]/2,
  4292. fromUnit = 'inch', toUnit = self.scalebarDict['unit'])
  4293. y = self.unitConv.convert(value = self.scalebarDict['where'][1] - self.scalebarDict['rect'].Get()[3]/2,
  4294. fromUnit = 'inch', toUnit = self.scalebarDict['unit'])
  4295. panel.position['xCtrl'].SetValue("%5.3f" % x)
  4296. panel.position['yCtrl'].SetValue("%5.3f" % y)
  4297. gridBagSizer.Add(panel.units['unitsLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4298. gridBagSizer.Add(panel.units['unitsCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4299. gridBagSizer.Add(panel.position['xLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4300. gridBagSizer.Add(panel.position['xCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4301. gridBagSizer.Add(panel.position['yLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4302. gridBagSizer.Add(panel.position['yCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4303. gridBagSizer.Add(panel.position['comment'], pos = (3,0), span = (1,2), flag =wx.ALIGN_BOTTOM, border = 0)
  4304. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  4305. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4306. #
  4307. # size
  4308. #
  4309. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size"))
  4310. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4311. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  4312. gridBagSizer.AddGrowableCol(1)
  4313. lengthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Length:"))
  4314. heightText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Height:"))
  4315. self.lengthTextCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, validator = TCValidator('DIGIT_ONLY'))
  4316. self.lengthTextCtrl.SetToolTipString(_("Scalebar length is given in map units"))
  4317. self.heightTextCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, validator = TCValidator('DIGIT_ONLY'))
  4318. self.heightTextCtrl.SetToolTipString(_("Scalebar height is real height on paper"))
  4319. choices = [_('default')] + self.unitConv.getMapUnitsNames()
  4320. self.unitsLength = wx.Choice(panel, id = wx.ID_ANY, choices = choices)
  4321. choices = self.unitConv.getPageUnitsNames()
  4322. self.unitsHeight = wx.Choice(panel, id = wx.ID_ANY, choices = choices)
  4323. # set values
  4324. unitName = self.unitConv.findName(self.scalebarDict['unitsLength'])
  4325. if unitName:
  4326. self.unitsLength.SetStringSelection(unitName)
  4327. else:
  4328. if self.scalebarDict['unitsLength'] == 'auto':
  4329. self.unitsLength.SetSelection(0)
  4330. elif self.scalebarDict['unitsLength'] == 'nautmiles':
  4331. self.unitsLength.SetStringSelection(self.unitConv.findName("nautical miles"))
  4332. self.unitsHeight.SetStringSelection(self.unitConv.findName(self.scalebarDict['unitsHeight']))
  4333. if self.scalebarDict['length']:
  4334. self.lengthTextCtrl.SetValue(str(self.scalebarDict['length']))
  4335. else: #estimate default
  4336. reg = grass.region()
  4337. w = int((reg['e'] - reg['w'])/3)
  4338. w = round(w, -len(str(w)) + 2) #12345 -> 12000
  4339. self.lengthTextCtrl.SetValue(str(w))
  4340. h = self.unitConv.convert(value = self.scalebarDict['height'], fromUnit = 'inch',
  4341. toUnit = self.scalebarDict['unitsHeight'])
  4342. self.heightTextCtrl.SetValue(str(h))
  4343. gridBagSizer.Add(lengthText, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4344. gridBagSizer.Add(self.lengthTextCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4345. gridBagSizer.Add(self.unitsLength, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  4346. gridBagSizer.Add(heightText, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4347. gridBagSizer.Add(self.heightTextCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4348. gridBagSizer.Add(self.unitsHeight, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  4349. sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  4350. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4351. #
  4352. #style
  4353. #
  4354. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Style"))
  4355. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4356. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  4357. sbTypeText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Type:"))
  4358. self.sbCombo = wx.combo.BitmapComboBox(panel, style = wx.CB_READONLY)
  4359. # only temporary, images must be moved away
  4360. imagePath = os.path.join(globalvar.ETCIMGDIR, "scalebar-fancy.png"), os.path.join(globalvar.ETCIMGDIR, "scalebar-simple.png")
  4361. for item, path in zip(['fancy', 'simple'], imagePath):
  4362. if not os.path.exists(path):
  4363. bitmap = wx.EmptyBitmap(0,0)
  4364. else:
  4365. bitmap = wx.Bitmap(path)
  4366. self.sbCombo.Append(item = '', bitmap = bitmap, clientData = item[0])
  4367. #self.sbCombo.Append(item = 'simple', bitmap = wx.Bitmap("./images/scalebar-simple.png"), clientData = 's')
  4368. if self.scalebarDict['scalebar'] == 'f':
  4369. self.sbCombo.SetSelection(0)
  4370. elif self.scalebarDict['scalebar'] == 's':
  4371. self.sbCombo.SetSelection(1)
  4372. sbSegmentsText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Number of segments:"))
  4373. self.sbSegmentsCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 4)
  4374. self.sbSegmentsCtrl.SetValue(self.scalebarDict['segment'])
  4375. sbLabelsText1 = wx.StaticText(panel, id = wx.ID_ANY, label = _("Label every "))
  4376. sbLabelsText2 = wx.StaticText(panel, id = wx.ID_ANY, label = _("segments"))
  4377. self.sbLabelsCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 1)
  4378. self.sbLabelsCtrl.SetValue(self.scalebarDict['numbers'])
  4379. #font
  4380. fontsizeText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Font size:"))
  4381. self.fontsizeCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 4, max = 30, initial = 10)
  4382. self.fontsizeCtrl.SetValue(self.scalebarDict['fontsize'])
  4383. self.backgroundCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent text background"))
  4384. if self.scalebarDict['background'] == 'y':
  4385. self.backgroundCheck.SetValue(False)
  4386. else:
  4387. self.backgroundCheck.SetValue(True)
  4388. gridBagSizer.Add(sbTypeText, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4389. gridBagSizer.Add(self.sbCombo, pos = (0,1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
  4390. gridBagSizer.Add(sbSegmentsText, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4391. gridBagSizer.Add(self.sbSegmentsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4392. gridBagSizer.Add(sbLabelsText1, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4393. gridBagSizer.Add(self.sbLabelsCtrl, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4394. gridBagSizer.Add(sbLabelsText2, pos = (2,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4395. gridBagSizer.Add(fontsizeText, pos = (3,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4396. gridBagSizer.Add(self.fontsizeCtrl, pos = (3,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4397. gridBagSizer.Add(self.backgroundCheck, pos = (4, 0), span = (1,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4398. sizer.Add(gridBagSizer, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL, border = 5)
  4399. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4400. panel.SetSizer(border)
  4401. return panel
  4402. def update(self):
  4403. """!Save information from dialog"""
  4404. #units
  4405. currUnit = self.unitConv.findUnit(self.panel.units['unitsCtrl'].GetStringSelection())
  4406. self.scalebarDict['unit'] = currUnit
  4407. # position
  4408. if self.panel.position['xCtrl'].GetValue():
  4409. x = self.panel.position['xCtrl'].GetValue()
  4410. else:
  4411. x = self.scalebarDict['where'][0]
  4412. if self.panel.position['yCtrl'].GetValue():
  4413. y = self.panel.position['yCtrl'].GetValue()
  4414. else:
  4415. y = self.scalebarDict['where'][1]
  4416. x = self.unitConv.convert(value = float(self.panel.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
  4417. y = self.unitConv.convert(value = float(self.panel.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch')
  4418. #style
  4419. self.scalebarDict['scalebar'] = self.sbCombo.GetClientData(self.sbCombo.GetSelection())
  4420. self.scalebarDict['segment'] = self.sbSegmentsCtrl.GetValue()
  4421. self.scalebarDict['numbers'] = self.sbLabelsCtrl.GetValue()
  4422. self.scalebarDict['fontsize'] = self.fontsizeCtrl.GetValue()
  4423. if self.backgroundCheck.GetValue():
  4424. self.scalebarDict['background'] = 'n'
  4425. else:
  4426. self.scalebarDict['background'] = 'y'
  4427. # size
  4428. # height
  4429. self.scalebarDict['unitsHeight'] = self.unitConv.findUnit(self.unitsHeight.GetStringSelection())
  4430. try:
  4431. height = float(self.heightTextCtrl.GetValue())
  4432. height = self.unitConv.convert(value = height, fromUnit = self.scalebarDict['unitsHeight'], toUnit = 'inch')
  4433. except (ValueError, SyntaxError):
  4434. height = 0.1 #default in inch
  4435. self.scalebarDict['height'] = height
  4436. #length
  4437. if self.unitsLength.GetSelection() == 0:
  4438. selected = 'auto'
  4439. else:
  4440. selected = self.unitConv.findUnit(self.unitsLength.GetStringSelection())
  4441. if selected == 'nautical miles':
  4442. selected = 'nautmiles'
  4443. self.scalebarDict['unitsLength'] = selected
  4444. try:
  4445. length = float(self.lengthTextCtrl.GetValue())
  4446. except (ValueError, SyntaxError):
  4447. wx.MessageBox(message = _("Length of scale bar is not defined"),
  4448. caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR)
  4449. return False
  4450. self.scalebarDict['length'] = length
  4451. # estimation of size
  4452. map = self.instruction.FindInstructionByType('map')
  4453. if not map:
  4454. map = self.instruction.FindInstructionByType('initMap')
  4455. mapId = map.id
  4456. rectSize = self.scalebar.EstimateSize(scalebarDict = self.scalebarDict,
  4457. scale = self.instruction[mapId]['scale'])
  4458. self.scalebarDict['rect'] = wx.Rect2D(x = x, y = y, w = rectSize[0], h = rectSize[1])
  4459. self.scalebarDict['where'] = self.scalebarDict['rect'].GetCentre()
  4460. if self.id not in self.instruction:
  4461. scalebar = Scalebar(self.id)
  4462. self.instruction.AddInstruction(scalebar)
  4463. self.instruction[self.id].SetInstruction(self.scalebarDict)
  4464. if self.id not in self.parent.objectId:
  4465. self.parent.objectId.append(self.id)
  4466. return True
  4467. def updateDialog(self):
  4468. """!Update scalebar coordinates, after moving"""
  4469. x, y = self.scalebarDict['rect'][:2]
  4470. currUnit = self.unitConv.findUnit(self.panel.units['unitsCtrl'].GetStringSelection())
  4471. x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit)
  4472. y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit)
  4473. self.panel.position['xCtrl'].SetValue("%5.3f" % x)
  4474. self.panel.position['yCtrl'].SetValue("%5.3f" % y)
  4475. class TextDialog(PsmapDialog):
  4476. def __init__(self, parent, id, settings):
  4477. PsmapDialog.__init__(self, parent = parent, id = id, title = "Text settings", settings = settings)
  4478. self.objectType = ('text',)
  4479. if self.id is not None:
  4480. self.textDict = self.instruction[id].GetInstruction()
  4481. else:
  4482. self.id = wx.NewId()
  4483. text = Text(self.id)
  4484. self.textDict = text.GetInstruction()
  4485. page = self.instruction.FindInstructionByType('page').GetInstruction()
  4486. self.textDict['where'] = page['Left'], page['Top']
  4487. map = self.instruction.FindInstructionByType('map')
  4488. if not map:
  4489. map = self.instruction.FindInstructionByType('initMap')
  4490. self.mapId = map.id
  4491. self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(map = map, x = self.textDict['where'][0], y = self.textDict['where'][1], paperToMap = True)
  4492. notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
  4493. self.textPanel = self._textPanel(notebook)
  4494. self.positionPanel = self._positionPanel(notebook)
  4495. self.OnBackground(None)
  4496. self.OnHighlight(None)
  4497. self.OnBorder(None)
  4498. self.OnPositionType(None)
  4499. self.OnRotation(None)
  4500. self._layout(notebook)
  4501. def _textPanel(self, notebook):
  4502. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
  4503. notebook.AddPage(page = panel, text = _("Text"))
  4504. border = wx.BoxSizer(wx.VERTICAL)
  4505. # text entry
  4506. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Text"))
  4507. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  4508. textLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Enter text:"))
  4509. self.textCtrl = ExpandoTextCtrl(panel, id = wx.ID_ANY, value = self.textDict['text'])
  4510. sizer.Add(textLabel, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
  4511. sizer.Add(self.textCtrl, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
  4512. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4513. #font
  4514. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Font settings"))
  4515. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4516. flexGridSizer = wx.FlexGridSizer (rows = 3, cols = 2, hgap = 5, vgap = 5)
  4517. flexGridSizer.AddGrowableCol(1)
  4518. self.AddFont(parent = panel, dialogDict = self.textDict)
  4519. flexGridSizer.Add(panel.font['fontLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4520. flexGridSizer.Add(panel.font['fontCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4521. flexGridSizer.Add(panel.font['fontSizeLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4522. flexGridSizer.Add(panel.font['fontSizeCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4523. flexGridSizer.Add(panel.font['colorLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4524. flexGridSizer.Add(panel.font['colorCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4525. sizer.Add(item = flexGridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
  4526. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4527. #text effects
  4528. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Text effects"))
  4529. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4530. gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
  4531. self.effect = {}
  4532. self.effect['backgroundCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("text background"))
  4533. self.effect['backgroundColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
  4534. self.effect['highlightCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("highlight"))
  4535. self.effect['highlightColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
  4536. self.effect['highlightWidth'] = wx.SpinCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize, min = 0, max = 5, initial = 1)
  4537. self.effect['highlightWidthLabel'] = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):"))
  4538. self.effect['borderCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("text border"))
  4539. self.effect['borderColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
  4540. self.effect['borderWidth'] = wx.SpinCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize, min = 1, max = 25, initial = 1)
  4541. self.effect['borderWidthLabel'] = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):"))
  4542. #set values
  4543. if self.textDict['background'] == None:
  4544. self.textDict['background'] = 'none'
  4545. if self.textDict['background'] != 'none':
  4546. self.effect['backgroundCtrl'].SetValue(True)
  4547. self.effect['backgroundColor'].SetColour(convertRGB(self.textDict['background']))
  4548. else:
  4549. self.effect['backgroundCtrl'].SetValue(False)
  4550. self.effect['backgroundColor'].SetColour(convertRGB('white'))
  4551. if self.textDict['hcolor'] == None:
  4552. self.textDict['hcolor'] = 'none'
  4553. if self.textDict['hcolor'] != 'none':
  4554. self.effect['highlightCtrl'].SetValue(True)
  4555. self.effect['highlightColor'].SetColour(convertRGB(self.textDict['hcolor']))
  4556. else:
  4557. self.effect['highlightCtrl'].SetValue(False)
  4558. self.effect['highlightColor'].SetColour(convertRGB('grey'))
  4559. self.effect['highlightWidth'].SetValue(float(self.textDict['hwidth']))
  4560. if self.textDict['border'] == None:
  4561. self.textDict['border'] = 'none'
  4562. if self.textDict['border'] != 'none':
  4563. self.effect['borderCtrl'].SetValue(True)
  4564. self.effect['borderColor'].SetColour(convertRGB(self.textDict['border']))
  4565. else:
  4566. self.effect['borderCtrl'].SetValue(False)
  4567. self.effect['borderColor'].SetColour(convertRGB('black'))
  4568. self.effect['borderWidth'].SetValue(float(self.textDict['width']))
  4569. gridBagSizer.Add(self.effect['backgroundCtrl'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4570. gridBagSizer.Add(self.effect['backgroundColor'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4571. gridBagSizer.Add(self.effect['highlightCtrl'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4572. gridBagSizer.Add(self.effect['highlightColor'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4573. gridBagSizer.Add(self.effect['highlightWidthLabel'], pos = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4574. gridBagSizer.Add(self.effect['highlightWidth'], pos = (1,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4575. gridBagSizer.Add(self.effect['borderCtrl'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4576. gridBagSizer.Add(self.effect['borderColor'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4577. gridBagSizer.Add(self.effect['borderWidthLabel'], pos = (2,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4578. gridBagSizer.Add(self.effect['borderWidth'], pos = (2,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4579. sizer.Add(item = gridBagSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
  4580. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4581. self.Bind(EVT_ETC_LAYOUT_NEEDED, self.OnRefit, self.textCtrl)
  4582. self.Bind(wx.EVT_CHECKBOX, self.OnBackground, self.effect['backgroundCtrl'])
  4583. self.Bind(wx.EVT_CHECKBOX, self.OnHighlight, self.effect['highlightCtrl'])
  4584. self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.effect['borderCtrl'])
  4585. panel.SetSizer(border)
  4586. panel.Fit()
  4587. return panel
  4588. def _positionPanel(self, notebook):
  4589. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
  4590. notebook.AddPage(page = panel, text = _("Position"))
  4591. border = wx.BoxSizer(wx.VERTICAL)
  4592. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position"))
  4593. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  4594. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  4595. gridBagSizer.AddGrowableCol(0)
  4596. gridBagSizer.AddGrowableCol(1)
  4597. #Position
  4598. self.AddExtendedPosition(panel, gridBagSizer, self.textDict)
  4599. #offset
  4600. box3 = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " %_("Offset"))
  4601. sizerO = wx.StaticBoxSizer(box3, wx.VERTICAL)
  4602. gridBagSizerO = wx.GridBagSizer (hgap = 5, vgap = 5)
  4603. self.xoffLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("horizontal (pts):"))
  4604. self.yoffLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("vertical (pts):"))
  4605. self.xoffCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, size = (50, -1), min = -50, max = 50, initial = 0)
  4606. self.yoffCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, size = (50, -1), min = -50, max = 50, initial = 0)
  4607. self.xoffCtrl.SetValue(self.textDict['xoffset'])
  4608. self.yoffCtrl.SetValue(self.textDict['yoffset'])
  4609. gridBagSizerO.Add(self.xoffLabel, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4610. gridBagSizerO.Add(self.yoffLabel, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4611. gridBagSizerO.Add(self.xoffCtrl, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4612. gridBagSizerO.Add(self.yoffCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4613. sizerO.Add(gridBagSizerO, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
  4614. gridBagSizer.Add(sizerO, pos = (3,0), flag = wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND, border = 0)
  4615. # reference point
  4616. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " %_(" Reference point"))
  4617. sizerR = wx.StaticBoxSizer(box, wx.VERTICAL)
  4618. flexSizer = wx.FlexGridSizer(rows = 3, cols = 3, hgap = 5, vgap = 5)
  4619. flexSizer.AddGrowableCol(0)
  4620. flexSizer.AddGrowableCol(1)
  4621. flexSizer.AddGrowableCol(2)
  4622. ref = []
  4623. for row in ["upper", "center", "lower"]:
  4624. for col in ["left", "center", "right"]:
  4625. ref.append(row + " " + col)
  4626. self.radio = [wx.RadioButton(panel, id = wx.ID_ANY, label = '', style = wx.RB_GROUP, name = ref[0])]
  4627. self.radio[0].SetValue(False)
  4628. flexSizer.Add(self.radio[0], proportion = 0, flag = wx.ALIGN_CENTER, border = 0)
  4629. for i in range(1,9):
  4630. self.radio.append(wx.RadioButton(panel, id = wx.ID_ANY, label = '', name = ref[i]))
  4631. self.radio[-1].SetValue(False)
  4632. flexSizer.Add(self.radio[-1], proportion = 0, flag = wx.ALIGN_CENTER, border = 0)
  4633. self.FindWindowByName(self.textDict['ref']).SetValue(True)
  4634. sizerR.Add(flexSizer, proportion = 1, flag = wx.EXPAND, border = 0)
  4635. gridBagSizer.Add(sizerR, pos = (3,1), flag = wx.ALIGN_LEFT|wx.EXPAND, border = 0)
  4636. sizer.Add(gridBagSizer, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5)
  4637. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4638. #rotation
  4639. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Text rotation"))
  4640. sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  4641. self.rotCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("rotate text (counterclockwise)"))
  4642. self.rotValue = wx.SpinCtrl(panel, wx.ID_ANY, size = (50, -1), min = 0, max = 360, initial = 0)
  4643. if self.textDict['rotate']:
  4644. self.rotValue.SetValue(int(self.textDict['rotate']))
  4645. self.rotCtrl.SetValue(True)
  4646. else:
  4647. self.rotValue.SetValue(0)
  4648. self.rotCtrl.SetValue(False)
  4649. sizer.Add(self.rotCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.ALL, border = 5)
  4650. sizer.Add(self.rotValue, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.ALL, border = 5)
  4651. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4652. panel.SetSizer(border)
  4653. panel.Fit()
  4654. self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toPaper'])
  4655. self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toMap'])
  4656. self.Bind(wx.EVT_CHECKBOX, self.OnRotation, self.rotCtrl)
  4657. return panel
  4658. def OnRefit(self, event):
  4659. self.Fit()
  4660. def OnRotation(self, event):
  4661. if self.rotCtrl.GetValue():
  4662. self.rotValue.Enable()
  4663. else:
  4664. self.rotValue.Disable()
  4665. def OnPositionType(self, event):
  4666. if self.positionPanel.position['toPaper'].GetValue():
  4667. for widget in self.gridBagSizerP.GetChildren():
  4668. widget.GetWindow().Enable()
  4669. for widget in self.gridBagSizerM.GetChildren():
  4670. widget.GetWindow().Disable()
  4671. else:
  4672. for widget in self.gridBagSizerM.GetChildren():
  4673. widget.GetWindow().Enable()
  4674. for widget in self.gridBagSizerP.GetChildren():
  4675. widget.GetWindow().Disable()
  4676. def OnBackground(self, event):
  4677. if self.effect['backgroundCtrl'].GetValue():
  4678. self.effect['backgroundColor'].Enable()
  4679. self.update()
  4680. else:
  4681. self.effect['backgroundColor'].Disable()
  4682. def OnHighlight(self, event):
  4683. if self.effect['highlightCtrl'].GetValue():
  4684. self.effect['highlightColor'].Enable()
  4685. self.effect['highlightWidth'].Enable()
  4686. self.effect['highlightWidthLabel'].Enable()
  4687. self.update()
  4688. else:
  4689. self.effect['highlightColor'].Disable()
  4690. self.effect['highlightWidth'].Disable()
  4691. self.effect['highlightWidthLabel'].Disable()
  4692. def OnBorder(self, event):
  4693. if self.effect['borderCtrl'].GetValue():
  4694. self.effect['borderColor'].Enable()
  4695. self.effect['borderWidth'].Enable()
  4696. self.effect['borderWidthLabel'].Enable()
  4697. self.update()
  4698. else:
  4699. self.effect['borderColor'].Disable()
  4700. self.effect['borderWidth'].Disable()
  4701. self.effect['borderWidthLabel'].Disable()
  4702. def update(self):
  4703. #text
  4704. self.textDict['text'] = self.textCtrl.GetValue()
  4705. if not self.textDict['text']:
  4706. wx.MessageBox(_("No text entered!"), _("Error"))
  4707. return False
  4708. #font
  4709. self.textDict['font'] = self.textPanel.font['fontCtrl'].GetStringSelection()
  4710. self.textDict['fontsize'] = self.textPanel.font['fontSizeCtrl'].GetValue()
  4711. color = self.textPanel.font['colorCtrl'].GetColour()
  4712. self.textDict['color'] = convertRGB(color)
  4713. #effects
  4714. if self.effect['backgroundCtrl'].GetValue():
  4715. background = self.effect['backgroundColor'].GetColour()
  4716. self.textDict['background'] = convertRGB(background)
  4717. else:
  4718. self.textDict['background'] = 'none'
  4719. if self.effect['borderCtrl'].GetValue():
  4720. border = self.effect['borderColor'].GetColour()
  4721. self.textDict['border'] = convertRGB(border)
  4722. else:
  4723. self.textDict['border'] = 'none'
  4724. self.textDict['width'] = self.effect['borderWidth'].GetValue()
  4725. if self.effect['highlightCtrl'].GetValue():
  4726. highlight = self.effect['highlightColor'].GetColour()
  4727. self.textDict['hcolor'] = convertRGB(highlight)
  4728. else:
  4729. self.textDict['hcolor'] = 'none'
  4730. self.textDict['hwidth'] = self.effect['highlightWidth'].GetValue()
  4731. #offset
  4732. self.textDict['xoffset'] = self.xoffCtrl.GetValue()
  4733. self.textDict['yoffset'] = self.yoffCtrl.GetValue()
  4734. #position
  4735. if self.positionPanel.position['toPaper'].GetValue():
  4736. self.textDict['XY'] = True
  4737. currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection())
  4738. self.textDict['unit'] = currUnit
  4739. if self.positionPanel.position['xCtrl'].GetValue():
  4740. x = self.positionPanel.position['xCtrl'].GetValue()
  4741. else:
  4742. x = self.textDict['where'][0]
  4743. if self.positionPanel.position['yCtrl'].GetValue():
  4744. y = self.positionPanel.position['yCtrl'].GetValue()
  4745. else:
  4746. y = self.textDict['where'][1]
  4747. x = self.unitConv.convert(value = float(x), fromUnit = currUnit, toUnit = 'inch')
  4748. y = self.unitConv.convert(value = float(y), fromUnit = currUnit, toUnit = 'inch')
  4749. self.textDict['where'] = x, y
  4750. self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(self.instruction[self.mapId], x, y, paperToMap = True)
  4751. else:
  4752. self.textDict['XY'] = False
  4753. if self.positionPanel.position['eCtrl'].GetValue():
  4754. self.textDict['east'] = self.positionPanel.position['eCtrl'].GetValue()
  4755. else:
  4756. self.textDict['east'] = self.textDict['east']
  4757. if self.positionPanel.position['nCtrl'].GetValue():
  4758. self.textDict['north'] = self.positionPanel.position['nCtrl'].GetValue()
  4759. else:
  4760. self.textDict['north'] = self.textDict['north']
  4761. self.textDict['where'] = PaperMapCoordinates(map = self.instruction[self.mapId], x = float(self.textDict['east']),
  4762. y = float(self.textDict['north']), paperToMap = False)
  4763. #rotation
  4764. if self.rotCtrl.GetValue():
  4765. self.textDict['rotate'] = self.rotValue.GetValue()
  4766. else:
  4767. self.textDict['rotate'] = None
  4768. #reference point
  4769. for radio in self.radio:
  4770. if radio.GetValue() == True:
  4771. self.textDict['ref'] = radio.GetName()
  4772. if self.id not in self.instruction:
  4773. text = Text(self.id)
  4774. self.instruction.AddInstruction(text)
  4775. self.instruction[self.id].SetInstruction(self.textDict)
  4776. if self.id not in self.parent.objectId:
  4777. self.parent.objectId.append(self.id)
  4778. # self.updateDialog()
  4779. return True
  4780. def updateDialog(self):
  4781. """!Update text coordinates, after moving"""
  4782. # XY coordinates
  4783. x, y = self.textDict['where'][:2]
  4784. currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection())
  4785. x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit)
  4786. y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit)
  4787. self.positionPanel.position['xCtrl'].SetValue("%5.3f" % x)
  4788. self.positionPanel.position['yCtrl'].SetValue("%5.3f" % y)
  4789. # EN coordinates
  4790. e, n = self.textDict['east'], self.textDict['north']
  4791. self.positionPanel.position['eCtrl'].SetValue(str(self.textDict['east']))
  4792. self.positionPanel.position['nCtrl'].SetValue(str(self.textDict['north']))
  4793. class ImageDialog(PsmapDialog):
  4794. """!Dialog for setting image properties.
  4795. It's base dialog for North Arrow dialog.
  4796. """
  4797. def __init__(self, parent, id, settings, imagePanelName = _("Image")):
  4798. PsmapDialog.__init__(self, parent = parent, id = id, title = "Image settings",
  4799. settings = settings)
  4800. self.objectType = ('image',)
  4801. if self.id is not None:
  4802. self.imageObj = self.instruction[self.id]
  4803. self.imageDict = self.instruction[id].GetInstruction()
  4804. else:
  4805. self.id = wx.NewId()
  4806. self.imageObj = self._newObject()
  4807. self.imageDict = self.imageObj.GetInstruction()
  4808. page = self.instruction.FindInstructionByType('page').GetInstruction()
  4809. self.imageDict['where'] = page['Left'], page['Top']
  4810. map = self.instruction.FindInstructionByType('map')
  4811. if not map:
  4812. map = self.instruction.FindInstructionByType('initMap')
  4813. self.mapId = map.id
  4814. self.imageDict['east'], self.imageDict['north'] = PaperMapCoordinates(map = map, x = self.imageDict['where'][0], y = self.imageDict['where'][1], paperToMap = True)
  4815. notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
  4816. self.imagePanelName = imagePanelName
  4817. self.imagePanel = self._imagePanel(notebook)
  4818. self.positionPanel = self._positionPanel(notebook)
  4819. self.OnPositionType(None)
  4820. if self.imageDict['epsfile']:
  4821. self.imagePanel.image['dir'].SetValue(os.path.dirname(self.imageDict['epsfile']))
  4822. else:
  4823. self.imagePanel.image['dir'].SetValue(self._getImageDirectory())
  4824. self.OnDirChanged(None)
  4825. self._layout(notebook)
  4826. def _newObject(self):
  4827. """!Create corresponding instruction object"""
  4828. return Image(self.id, self.instruction)
  4829. def _imagePanel(self, notebook):
  4830. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
  4831. notebook.AddPage(page = panel, text = self.imagePanelName)
  4832. border = wx.BoxSizer(wx.VERTICAL)
  4833. #
  4834. # choose image
  4835. #
  4836. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Image"))
  4837. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4838. # choose directory
  4839. panel.image = {}
  4840. if self.imageDict['epsfile']:
  4841. startDir = os.path.dirname(self.imageDict['epsfile'])
  4842. else:
  4843. startDir = self._getImageDirectory()
  4844. dir = filebrowse.DirBrowseButton(parent = panel, id = wx.ID_ANY,
  4845. labelText = _("Choose a directory:"),
  4846. dialogTitle = _("Choose a directory with images"),
  4847. buttonText = _('Browse'),
  4848. startDirectory = startDir,
  4849. changeCallback = self.OnDirChanged)
  4850. panel.image['dir'] = dir
  4851. sizer.Add(item = dir, proportion = 0, flag = wx.EXPAND, border = 0)
  4852. # image list
  4853. hSizer = wx.BoxSizer(wx.HORIZONTAL)
  4854. imageList = wx.ListBox(parent = panel, id = wx.ID_ANY)
  4855. panel.image['list'] = imageList
  4856. imageList.Bind(wx.EVT_LISTBOX, self.OnImageSelectionChanged)
  4857. hSizer.Add(item = imageList, proportion = 1, flag = wx.EXPAND | wx.RIGHT, border = 10)
  4858. # image preview
  4859. vSizer = wx.BoxSizer(wx.VERTICAL)
  4860. self.previewSize = (150, 150)
  4861. img = wx.EmptyImage(*self.previewSize)
  4862. panel.image['preview'] = wx.StaticBitmap(parent = panel, id = wx.ID_ANY,
  4863. bitmap = wx.BitmapFromImage(img))
  4864. vSizer.Add(item = panel.image['preview'], proportion = 0, flag = wx.EXPAND | wx.BOTTOM, border = 5)
  4865. panel.image['sizeInfo'] = wx.StaticText(parent = panel, id = wx.ID_ANY)
  4866. vSizer.Add(item = panel.image['sizeInfo'], proportion = 0, flag = wx.ALIGN_CENTER, border = 0)
  4867. hSizer.Add(item = vSizer, proportion = 0, flag = wx.EXPAND, border = 0)
  4868. sizer.Add(item = hSizer, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 3)
  4869. epsInfo = wx.StaticText(parent = panel, id = wx.ID_ANY,
  4870. label = _("Note: only EPS format supported"))
  4871. sizer.Add(item = epsInfo, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 3)
  4872. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4873. #
  4874. # rotation
  4875. #
  4876. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Scale And Rotation"))
  4877. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4878. gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  4879. scaleLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Scale:"))
  4880. if fs:
  4881. panel.image['scale'] = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 50,
  4882. increment = 0.5, value = 1, style = fs.FS_RIGHT, size = self.spinCtrlSize)
  4883. panel.image['scale'].SetFormat("%f")
  4884. panel.image['scale'].SetDigits(1)
  4885. else:
  4886. panel.image['scale'] = wx.TextCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize,
  4887. validator = TCValidator(flag = 'DIGIT_ONLY'))
  4888. if self.imageDict['scale']:
  4889. if fs:
  4890. value = float(self.imageDict['scale'])
  4891. else:
  4892. value = str(self.imageDict['scale'])
  4893. else:
  4894. if fs:
  4895. value = 0
  4896. else:
  4897. value = '0'
  4898. panel.image['scale'].SetValue(value)
  4899. gridSizer.Add(item = scaleLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
  4900. gridSizer.Add(item = panel.image['scale'], pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL)
  4901. rotLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Rotation angle (deg):"))
  4902. if fs:
  4903. panel.image['rotate'] = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 360,
  4904. increment = 0.5, value = 0, style = fs.FS_RIGHT, size = self.spinCtrlSize)
  4905. panel.image['rotate'].SetFormat("%f")
  4906. panel.image['rotate'].SetDigits(1)
  4907. else:
  4908. panel.image['rotate'] = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = self.spinCtrlSize,
  4909. min = 0, max = 359, initial = 0)
  4910. panel.image['rotate'].SetToolTipString(_("Counterclockwise rotation in degrees"))
  4911. if self.imageDict['rotate']:
  4912. panel.image['rotate'].SetValue(int(self.imageDict['rotate']))
  4913. else:
  4914. panel.image['rotate'].SetValue(0)
  4915. gridSizer.Add(item = rotLabel, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
  4916. gridSizer.Add(item = panel.image['rotate'], pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL)
  4917. self._addConvergence(panel = panel, gridBagSizer = gridSizer)
  4918. sizer.Add(item = gridSizer, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 5)
  4919. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4920. panel.SetSizer(border)
  4921. panel.Fit()
  4922. return panel
  4923. def _positionPanel(self, notebook):
  4924. panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
  4925. notebook.AddPage(page = panel, text = _("Position"))
  4926. border = wx.BoxSizer(wx.VERTICAL)
  4927. #
  4928. # set position
  4929. #
  4930. box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position"))
  4931. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  4932. gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  4933. gridBagSizer.AddGrowableCol(0)
  4934. gridBagSizer.AddGrowableCol(1)
  4935. self.AddExtendedPosition(panel, gridBagSizer, self.imageDict)
  4936. self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toPaper'])
  4937. self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toMap'])
  4938. sizer.Add(gridBagSizer, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL| wx.ALL, border = 5)
  4939. border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
  4940. panel.SetSizer(border)
  4941. panel.Fit()
  4942. return panel
  4943. def OnDirChanged(self, event):
  4944. """!Image directory changed"""
  4945. path = self.imagePanel.image['dir'].GetValue()
  4946. try:
  4947. files = os.listdir(path)
  4948. except OSError: # no such directory
  4949. files = []
  4950. imageList = []
  4951. # no setter for startDirectory?
  4952. try:
  4953. self.imagePanel.image['dir'].startDirectory = path
  4954. except AttributeError: # for sure
  4955. pass
  4956. for file in files:
  4957. if os.path.splitext(file)[1].lower() == '.eps':
  4958. imageList.append(file)
  4959. imageList.sort()
  4960. self.imagePanel.image['list'].SetItems(imageList)
  4961. if self.imageDict['epsfile']:
  4962. file = os.path.basename(self.imageDict['epsfile'])
  4963. self.imagePanel.image['list'].SetStringSelection(file)
  4964. else:
  4965. self.imagePanel.image['list'].SetSelection(0)
  4966. self.OnImageSelectionChanged(None)
  4967. def OnPositionType(self, event):
  4968. if self.positionPanel.position['toPaper'].GetValue():
  4969. for widget in self.gridBagSizerP.GetChildren():
  4970. widget.GetWindow().Enable()
  4971. for widget in self.gridBagSizerM.GetChildren():
  4972. widget.GetWindow().Disable()
  4973. else:
  4974. for widget in self.gridBagSizerM.GetChildren():
  4975. widget.GetWindow().Enable()
  4976. for widget in self.gridBagSizerP.GetChildren():
  4977. widget.GetWindow().Disable()
  4978. def _getImageDirectory(self):
  4979. """!Default image directory"""
  4980. return os.getcwd()
  4981. def _addConvergence(self, panel, gridBagSizer):
  4982. pass
  4983. def OnImageSelectionChanged(self, event):
  4984. """!Image selected, show preview and size"""
  4985. if not self.imagePanel.image['dir']: # event is emitted when closing dialog an it causes error
  4986. return
  4987. if not havePILImage:
  4988. self.DrawWarningText(_("PIL\nmissing"))
  4989. return
  4990. imageName = self.imagePanel.image['list'].GetStringSelection()
  4991. if not imageName:
  4992. self.ClearPreview()
  4993. return
  4994. basePath = self.imagePanel.image['dir'].GetValue()
  4995. file = os.path.join(basePath, imageName)
  4996. if not os.path.exists(file):
  4997. return
  4998. if os.path.splitext(file)[1].lower() == '.eps':
  4999. try:
  5000. pImg = PILImage.open(file)
  5001. img = PilImageToWxImage(pImg)
  5002. except IOError, e:
  5003. GError(message = _("Unable to read file %s") % file)
  5004. self.ClearPreview()
  5005. return
  5006. self.SetSizeInfoLabel(img)
  5007. img = self.ScaleToPreview(img)
  5008. bitmap = img.ConvertToBitmap()
  5009. self.DrawBitmap(bitmap)
  5010. else:
  5011. # TODO: read other formats and convert by PIL to eps
  5012. pass
  5013. def ScaleToPreview(self, img):
  5014. """!Scale image to preview size"""
  5015. w = img.GetWidth()
  5016. h = img.GetHeight()
  5017. if w <= self.previewSize[0] and h <= self.previewSize[1]:
  5018. return img
  5019. if w > h:
  5020. newW = self.previewSize[0]
  5021. newH = self.previewSize[0] * h / w
  5022. else:
  5023. newH = self.previewSize[0]
  5024. newW = self.previewSize[0] * w / h
  5025. return img.Scale(newW, newH, wx.IMAGE_QUALITY_HIGH)
  5026. def DrawWarningText(self, warning):
  5027. """!Draw text on preview window"""
  5028. buffer = wx.EmptyBitmap(*self.previewSize)
  5029. dc = wx.MemoryDC()
  5030. dc.SelectObject(buffer)
  5031. dc.SetBrush(wx.Brush(wx.Color(250, 250, 250)))
  5032. dc.Clear()
  5033. extent = dc.GetTextExtent(warning)
  5034. posX = self.previewSize[0] / 2 - extent[0] / 2
  5035. posY = self.previewSize[1] / 2 - extent[1] / 2
  5036. dc.DrawText(warning, posX, posY)
  5037. self.imagePanel.image['preview'].SetBitmap(buffer)
  5038. dc.SelectObject(wx.NullBitmap)
  5039. def DrawBitmap(self, bitmap):
  5040. """!Draw bitmap, center it if smaller than preview size"""
  5041. if bitmap.GetWidth() <= self.previewSize[0] and bitmap.GetHeight() <= self.previewSize[1]:
  5042. buffer = wx.EmptyBitmap(*self.previewSize)
  5043. dc = wx.MemoryDC()
  5044. dc.SelectObject(buffer)
  5045. dc.SetBrush(dc.GetBrush())
  5046. dc.Clear()
  5047. posX = self.previewSize[0] / 2 - bitmap.GetWidth() / 2
  5048. posY = self.previewSize[1] / 2 - bitmap.GetHeight() / 2
  5049. dc.DrawBitmap(bitmap, posX, posY)
  5050. self.imagePanel.image['preview'].SetBitmap(buffer)
  5051. dc.SelectObject(wx.NullBitmap)
  5052. else:
  5053. self.imagePanel.image['preview'].SetBitmap(bitmap)
  5054. def SetSizeInfoLabel(self, image):
  5055. """!Update image size label"""
  5056. self.imagePanel.image['sizeInfo'].SetLabel(_("size: %s x %s pts") % (image.GetWidth(), image.GetHeight()))
  5057. self.imagePanel.image['sizeInfo'].GetContainingSizer().Layout()
  5058. def ClearPreview(self):
  5059. """!Clear preview window"""
  5060. buffer = wx.EmptyBitmap(*self.previewSize)
  5061. dc = wx.MemoryDC()
  5062. dc.SelectObject(buffer)
  5063. dc.SetBrush(wx.WHITE_BRUSH)
  5064. dc.Clear()
  5065. mask = wx.Mask(buffer, wx.WHITE)
  5066. buffer.SetMask(mask)
  5067. self.imagePanel.image['preview'].SetBitmap(buffer)
  5068. dc.SelectObject(wx.NullBitmap)
  5069. def update(self):
  5070. # epsfile
  5071. selected = self.imagePanel.image['list'].GetStringSelection()
  5072. basePath = self.imagePanel.image['dir'].GetValue()
  5073. if not selected:
  5074. gcmd.GMessage(parent = self, message = _("No image selected."))
  5075. return False
  5076. self.imageDict['epsfile'] = os.path.join(basePath, selected)
  5077. #position
  5078. if self.positionPanel.position['toPaper'].GetValue():
  5079. self.imageDict['XY'] = True
  5080. currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection())
  5081. self.imageDict['unit'] = currUnit
  5082. if self.positionPanel.position['xCtrl'].GetValue():
  5083. x = self.positionPanel.position['xCtrl'].GetValue()
  5084. else:
  5085. x = self.imageDict['where'][0]
  5086. if self.positionPanel.position['yCtrl'].GetValue():
  5087. y = self.positionPanel.position['yCtrl'].GetValue()
  5088. else:
  5089. y = self.imageDict['where'][1]
  5090. x = self.unitConv.convert(value = float(x), fromUnit = currUnit, toUnit = 'inch')
  5091. y = self.unitConv.convert(value = float(y), fromUnit = currUnit, toUnit = 'inch')
  5092. self.imageDict['where'] = x, y
  5093. else:
  5094. self.imageDict['XY'] = False
  5095. if self.positionPanel.position['eCtrl'].GetValue():
  5096. e = self.positionPanel.position['eCtrl'].GetValue()
  5097. else:
  5098. self.imageDict['east'] = self.imageDict['east']
  5099. if self.positionPanel.position['nCtrl'].GetValue():
  5100. n = self.positionPanel.position['nCtrl'].GetValue()
  5101. else:
  5102. self.imageDict['north'] = self.imageDict['north']
  5103. x, y = PaperMapCoordinates(map = self.instruction[self.mapId], x = float(self.imageDict['east']),
  5104. y = float(self.imageDict['north']), paperToMap = False)
  5105. #rotation
  5106. rot = self.imagePanel.image['rotate'].GetValue()
  5107. if rot == 0:
  5108. self.imageDict['rotate'] = None
  5109. else:
  5110. self.imageDict['rotate'] = rot
  5111. #scale
  5112. self.imageDict['scale'] = self.imagePanel.image['scale'].GetValue()
  5113. # scale
  5114. w, h = self.imageObj.GetImageOrigSize(self.imageDict['epsfile'])
  5115. if self.imageDict['rotate']:
  5116. self.imageDict['size'] = BBoxAfterRotation(w, h, self.imageDict['rotate'])
  5117. else:
  5118. self.imageDict['size'] = w, h
  5119. w = self.unitConv.convert(value = self.imageDict['size'][0],
  5120. fromUnit = 'point', toUnit = 'inch')
  5121. h = self.unitConv.convert(value = self.imageDict['size'][1],
  5122. fromUnit = 'point', toUnit = 'inch')
  5123. self.imageDict['rect'] = wx.Rect2D(x = x, y = y,
  5124. w = w * self.imageDict['scale'],
  5125. h = h * self.imageDict['scale'])
  5126. if self.id not in self.instruction:
  5127. image = self._newObject()
  5128. self.instruction.AddInstruction(image)
  5129. self.instruction[self.id].SetInstruction(self.imageDict)
  5130. if self.id not in self.parent.objectId:
  5131. self.parent.objectId.append(self.id)
  5132. return True
  5133. def updateDialog(self):
  5134. """!Update text coordinates, after moving"""
  5135. # XY coordinates
  5136. x, y = self.imageDict['where'][:2]
  5137. currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection())
  5138. x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit)
  5139. y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit)
  5140. self.positionPanel.position['xCtrl'].SetValue("%5.3f" % x)
  5141. self.positionPanel.position['yCtrl'].SetValue("%5.3f" % y)
  5142. # EN coordinates
  5143. e, n = self.imageDict['east'], self.imageDict['north']
  5144. self.positionPanel.position['eCtrl'].SetValue(str(self.imageDict['east']))
  5145. self.positionPanel.position['nCtrl'].SetValue(str(self.imageDict['north']))
  5146. class NorthArrowDialog(ImageDialog):
  5147. def __init__(self, parent, id, settings):
  5148. ImageDialog.__init__(self, parent = parent, id = id, settings = settings,
  5149. imagePanelName = _("North Arrow"))
  5150. self.objectType = ('northArrow',)
  5151. self.SetTitle(_("North Arrow settings"))
  5152. def _newObject(self):
  5153. return NorthArrow(self.id, self.instruction)
  5154. def _getImageDirectory(self):
  5155. gisbase = os.getenv("GISBASE")
  5156. return os.path.join(gisbase, 'etc', 'paint', 'decorations')
  5157. def _addConvergence(self, panel, gridBagSizer):
  5158. convergence = wx.Button(parent = panel, id = wx.ID_ANY,
  5159. label = _("Compute convergence"))
  5160. gridBagSizer.Add(item = convergence, pos = (1, 2),
  5161. flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
  5162. convergence.Bind(wx.EVT_BUTTON, self.OnConvergence)
  5163. panel.image['convergence'] = convergence
  5164. def OnConvergence(self, event):
  5165. ret = RunCommand('g.region', read = True, flags = 'ng')
  5166. if ret:
  5167. convergence = float(ret.strip().split('=')[1])
  5168. if convergence < 0:
  5169. self.imagePanel.image['rotate'].SetValue(abs(convergence))
  5170. else:
  5171. self.imagePanel.image['rotate'].SetValue(360 - convergence)
  5172. def convertRGB(rgb):
  5173. """!Converts wx.Colour(r,g,b,a) to string 'r:g:b' or named color,
  5174. or named color/r:g:b string to wx.Colour, depending on input"""
  5175. # transform a wx.Colour tuple into an r:g:b string
  5176. if type(rgb) == wx.Colour:
  5177. for name, color in grass.named_colors.items():
  5178. if rgb.Red() == int(color[0] * 255) and\
  5179. rgb.Green() == int(color[1] * 255) and\
  5180. rgb.Blue() == int(color[2] * 255):
  5181. return name
  5182. return str(rgb.Red()) + ':' + str(rgb.Green()) + ':' + str(rgb.Blue())
  5183. # transform a GRASS named color or an r:g:b string into a wx.Colour tuple
  5184. else:
  5185. color = (grass.parse_color(rgb)[0]*255,
  5186. grass.parse_color(rgb)[1]*255,
  5187. grass.parse_color(rgb)[2]*255)
  5188. color = wx.Color(*color)
  5189. if color.IsOk():
  5190. return color
  5191. else:
  5192. return None
  5193. def PaperMapCoordinates(map, x, y, paperToMap = True):
  5194. """!Converts paper (inch) coordinates -> map coordinates"""
  5195. unitConv = UnitConversion()
  5196. currRegionDict = grass.region()
  5197. cornerEasting, cornerNorthing = currRegionDict['w'], currRegionDict['n']
  5198. xMap = map['rect'][0]
  5199. yMap = map['rect'][1]
  5200. widthMap = map['rect'][2] * 0.0254 # to meter
  5201. heightMap = map['rect'][3] * 0.0254
  5202. xScale = widthMap / abs(currRegionDict['w'] - currRegionDict['e'])
  5203. yScale = heightMap / abs(currRegionDict['n'] - currRegionDict['s'])
  5204. currScale = (xScale + yScale) / 2
  5205. if not paperToMap:
  5206. textEasting, textNorthing = x, y
  5207. eastingDiff = textEasting - cornerEasting
  5208. if currRegionDict['w'] > currRegionDict['e']:
  5209. eastingDiff = - eastingDiff
  5210. else:
  5211. eastingDiff = eastingDiff
  5212. northingDiff = textNorthing - cornerNorthing
  5213. if currRegionDict['n'] > currRegionDict['s']:
  5214. northingDiff = - northingDiff
  5215. else:
  5216. northingDiff = northingDiff
  5217. xPaper = xMap + unitConv.convert(value = eastingDiff, fromUnit = 'meter', toUnit = 'inch') * currScale
  5218. yPaper = yMap + unitConv.convert(value = northingDiff, fromUnit = 'meter', toUnit = 'inch') * currScale
  5219. return xPaper, yPaper
  5220. else:
  5221. if currRegionDict['w'] < currRegionDict['e']:
  5222. eastingDiff = (x - xMap)
  5223. else:
  5224. eastingDiff = (xMap - x)
  5225. if currRegionDict['n'] < currRegionDict['s']:
  5226. northingDiff = (y - yMap)
  5227. else:
  5228. northingDiff = (yMap - y)
  5229. textEasting = cornerEasting + unitConv.convert(value = eastingDiff, fromUnit = 'inch', toUnit = 'meter') / currScale
  5230. textNorthing = cornerNorthing + unitConv.convert(value = northingDiff, fromUnit = 'inch', toUnit = 'meter') / currScale
  5231. return int(textEasting), int(textNorthing)
  5232. def AutoAdjust(self, scaleType, rect, map = None, mapType = None, region = None):
  5233. """!Computes map scale, center and map frame rectangle to fit region (scale is not fixed)"""
  5234. currRegionDict = {}
  5235. if scaleType == 0 and map:# automatic, region from raster or vector
  5236. res = ''
  5237. if mapType == 'raster':
  5238. try:
  5239. res = grass.read_command("g.region", flags = 'gu', rast = map)
  5240. except grass.ScriptError:
  5241. pass
  5242. elif mapType == 'vector':
  5243. res = grass.read_command("g.region", flags = 'gu', vect = map)
  5244. currRegionDict = grass.parse_key_val(res, val_type = float)
  5245. elif scaleType == 1 and region: # saved region
  5246. res = grass.read_command("g.region", flags = 'gu', region = region)
  5247. currRegionDict = grass.parse_key_val(res, val_type = float)
  5248. elif scaleType == 2: # current region
  5249. env = grass.gisenv()
  5250. windFilePath = os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], 'WIND')
  5251. try:
  5252. windFile = open(windFilePath, 'r').read()
  5253. except IOError:
  5254. currRegionDict = grass.region()
  5255. regionDict = grass.parse_key_val(windFile, sep = ':', val_type = float)
  5256. region = grass.read_command("g.region", flags = 'gu', n = regionDict['north'], s = regionDict['south'],
  5257. e = regionDict['east'], w = regionDict['west'])
  5258. currRegionDict = grass.parse_key_val(region, val_type = float)
  5259. else:
  5260. return None, None, None
  5261. if not currRegionDict:
  5262. return None, None, None
  5263. rX = rect.x
  5264. rY = rect.y
  5265. rW = rect.width
  5266. rH = rect.height
  5267. if not hasattr(self, 'unitConv'):
  5268. self.unitConv = UnitConversion(self)
  5269. toM = 1
  5270. if projInfo()['proj'] != 'xy':
  5271. toM = float(projInfo()['meters'])
  5272. mW = self.unitConv.convert(value = (currRegionDict['e'] - currRegionDict['w']) * toM, fromUnit = 'meter', toUnit = 'inch')
  5273. mH = self.unitConv.convert(value = (currRegionDict['n'] - currRegionDict['s']) * toM, fromUnit = 'meter', toUnit = 'inch')
  5274. scale = min(rW/mW, rH/mH)
  5275. if rW/rH > mW/mH:
  5276. x = rX - (rH*(mW/mH) - rW)/2
  5277. y = rY
  5278. rWNew = rH*(mW/mH)
  5279. rHNew = rH
  5280. else:
  5281. x = rX
  5282. y = rY - (rW*(mH/mW) - rH)/2
  5283. rHNew = rW*(mH/mW)
  5284. rWNew = rW
  5285. # center
  5286. cE = (currRegionDict['w'] + currRegionDict['e'])/2
  5287. cN = (currRegionDict['n'] + currRegionDict['s'])/2
  5288. return scale, (cE, cN), wx.Rect2D(x, y, rWNew, rHNew) #inch
  5289. def SetResolution(dpi, width, height):
  5290. """!If resolution is too high, lower it
  5291. @param dpi max DPI
  5292. @param width map frame width
  5293. @param height map frame height
  5294. """
  5295. region = grass.region()
  5296. if region['cols'] > width * dpi or region['rows'] > height * dpi:
  5297. rows = height * dpi
  5298. cols = width * dpi
  5299. RunCommand('g.region', rows = rows, cols = cols)
  5300. def ComputeSetRegion(self, mapDict):
  5301. """!Computes and sets region from current scale, map center coordinates and map rectangle"""
  5302. if mapDict['scaleType'] == 3: # fixed scale
  5303. scale = mapDict['scale']
  5304. if not hasattr(self, 'unitConv'):
  5305. self.unitConv = UnitConversion(self)
  5306. fromM = 1
  5307. if projInfo()['proj'] != 'xy':
  5308. fromM = float(projInfo()['meters'])
  5309. rectHalfInch = (mapDict['rect'].width/2, mapDict['rect'].height/2)
  5310. rectHalfMeter = (self.unitConv.convert(value = rectHalfInch[0], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale,
  5311. self.unitConv.convert(value = rectHalfInch[1], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale)
  5312. centerE = mapDict['center'][0]
  5313. centerN = mapDict['center'][1]
  5314. raster = self.instruction.FindInstructionByType('raster')
  5315. if raster:
  5316. rasterId = raster.id
  5317. else:
  5318. rasterId = None
  5319. if rasterId:
  5320. RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]),
  5321. s = floor(centerN - rectHalfMeter[1]),
  5322. e = ceil(centerE + rectHalfMeter[0]),
  5323. w = floor(centerE - rectHalfMeter[0]),
  5324. rast = self.instruction[rasterId]['raster'])
  5325. else:
  5326. RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]),
  5327. s = floor(centerN - rectHalfMeter[1]),
  5328. e = ceil(centerE + rectHalfMeter[0]),
  5329. w = floor(centerE - rectHalfMeter[0]))
  5330. def projInfo():
  5331. """!Return region projection and map units information,
  5332. taken from render.py"""
  5333. projinfo = dict()
  5334. ret = RunCommand('g.proj', read = True, flags = 'p')
  5335. if not ret:
  5336. return projinfo
  5337. for line in ret.splitlines():
  5338. if ':' in line:
  5339. key, val = line.split(':')
  5340. projinfo[key.strip()] = val.strip()
  5341. elif "XY location (unprojected)" in line:
  5342. projinfo['proj'] = 'xy'
  5343. projinfo['units'] = ''
  5344. break
  5345. return projinfo
  5346. def GetMapBounds(filename, portrait = True):
  5347. """!Run ps.map -b to get information about map bounding box
  5348. @param filename psmap input file
  5349. @param portrait page orientation"""
  5350. orient = ''
  5351. if not portrait:
  5352. orient = 'r'
  5353. try:
  5354. bb = map(float, grass.read_command('ps.map',
  5355. flags = 'b' + orient,
  5356. quiet = True,
  5357. input = filename).strip().split('=')[1].split(','))
  5358. except (grass.ScriptError, IndexError):
  5359. GError(message = _("Unable to run `ps.map -b`"))
  5360. return None
  5361. return wx.Rect2D(bb[0], bb[3], bb[2] - bb[0], bb[1] - bb[3])
  5362. def getRasterType(map):
  5363. """!Returns type of raster map (CELL, FCELL, DCELL)"""
  5364. if map is None:
  5365. map = ''
  5366. file = grass.find_file(name = map, element = 'cell')
  5367. if file['file']:
  5368. rasterType = grass.raster_info(map)['datatype']
  5369. return rasterType
  5370. else:
  5371. return None
  5372. def PilImageToWxImage(pilImage, copyAlpha = True):
  5373. """!Convert PIL image to wx.Image
  5374. Based on http://wiki.wxpython.org/WorkingWithImages
  5375. """
  5376. hasAlpha = pilImage.mode[-1] == 'A'
  5377. if copyAlpha and hasAlpha : # Make sure there is an alpha layer copy.
  5378. wxImage = wx.EmptyImage( *pilImage.size )
  5379. pilImageCopyRGBA = pilImage.copy()
  5380. pilImageCopyRGB = pilImageCopyRGBA.convert('RGB') # RGBA --> RGB
  5381. pilImageRgbData = pilImageCopyRGB.tostring()
  5382. wxImage.SetData(pilImageRgbData)
  5383. wxImage.SetAlphaData(pilImageCopyRGBA.tostring()[3::4]) # Create layer and insert alpha values.
  5384. else : # The resulting image will not have alpha.
  5385. wxImage = wx.EmptyImage(*pilImage.size)
  5386. pilImageCopy = pilImage.copy()
  5387. pilImageCopyRGB = pilImageCopy.convert('RGB') # Discard any alpha from the PIL image.
  5388. pilImageRgbData = pilImageCopyRGB.tostring()
  5389. wxImage.SetData(pilImageRgbData)
  5390. return wxImage
  5391. def BBoxAfterRotation(w, h, angle):
  5392. """!Compute bounding box or rotated rectangle
  5393. @param w rectangle width
  5394. @param h rectangle height
  5395. @param angle angle (0, 360) in degrees
  5396. """
  5397. angleRad = angle / 180. * pi
  5398. ct = cos(angleRad)
  5399. st = sin(angleRad)
  5400. hct = h * ct
  5401. wct = w * ct
  5402. hst = h * st
  5403. wst = w * st
  5404. y = x = 0
  5405. if 0 < angle <= 90:
  5406. y_min = y
  5407. y_max = y + hct + wst
  5408. x_min = x - hst
  5409. x_max = x + wct
  5410. elif 90 < angle <= 180:
  5411. y_min = y + hct
  5412. y_max = y + wst
  5413. x_min = x - hst + wct
  5414. x_max = x
  5415. elif 180 < angle <= 270:
  5416. y_min = y + wst + hct
  5417. y_max = y
  5418. x_min = x + wct
  5419. x_max = x - hst
  5420. elif 270 < angle <= 360:
  5421. y_min = y + wst
  5422. y_max = y + hct
  5423. x_min = x
  5424. x_max = x + wct - hst
  5425. width = int(ceil(abs(x_max) + abs(x_min)))
  5426. height = int(ceil(abs(y_max) + abs(y_min)))
  5427. return width, height