property.cpp 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/propgrid/property.cpp
  3. // Purpose: wxPGProperty and related support classes
  4. // Author: Jaakko Salli
  5. // Modified by:
  6. // Created: 2008-08-23
  7. // Copyright: (c) Jaakko Salli
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. // For compilers that support precompilation, includes "wx/wx.h".
  11. #include "wx/wxprec.h"
  12. #ifdef __BORLANDC__
  13. #pragma hdrstop
  14. #endif
  15. #if wxUSE_PROPGRID
  16. #ifndef WX_PRECOMP
  17. #include "wx/defs.h"
  18. #include "wx/object.h"
  19. #include "wx/hash.h"
  20. #include "wx/string.h"
  21. #include "wx/log.h"
  22. #include "wx/math.h"
  23. #include "wx/event.h"
  24. #include "wx/window.h"
  25. #include "wx/panel.h"
  26. #include "wx/dc.h"
  27. #include "wx/dcmemory.h"
  28. #include "wx/pen.h"
  29. #include "wx/brush.h"
  30. #include "wx/settings.h"
  31. #include "wx/intl.h"
  32. #endif
  33. #include "wx/image.h"
  34. #include "wx/propgrid/propgrid.h"
  35. #define PWC_CHILD_SUMMARY_LIMIT 16 // Maximum number of children summarized in a parent property's
  36. // value field.
  37. #define PWC_CHILD_SUMMARY_CHAR_LIMIT 64 // Character limit of summary field when not editing
  38. #if wxPG_COMPATIBILITY_1_4
  39. // Used to establish backwards compatibility
  40. const char* g_invalidStringContent = "@__TOTALLY_INVALID_STRING__@";
  41. #endif
  42. // -----------------------------------------------------------------------
  43. static void wxPGDrawFocusRect( wxDC& dc, const wxRect& rect )
  44. {
  45. #if defined(__WXMSW__) && !defined(__WXWINCE__)
  46. // FIXME: Use DrawFocusRect code above (currently it draws solid line
  47. // for caption focus but works ok for other stuff).
  48. // Also, it seems that this code may not work in future wx versions.
  49. dc.SetLogicalFunction(wxINVERT);
  50. wxPen pen(*wxBLACK,1,wxDOT);
  51. pen.SetCap(wxCAP_BUTT);
  52. dc.SetPen(pen);
  53. dc.SetBrush(*wxTRANSPARENT_BRUSH);
  54. dc.DrawRectangle(rect);
  55. dc.SetLogicalFunction(wxCOPY);
  56. #else
  57. dc.SetLogicalFunction(wxINVERT);
  58. dc.SetPen(wxPen(*wxBLACK,1,wxDOT));
  59. dc.SetBrush(*wxTRANSPARENT_BRUSH);
  60. dc.DrawRectangle(rect);
  61. dc.SetLogicalFunction(wxCOPY);
  62. #endif
  63. }
  64. // -----------------------------------------------------------------------
  65. // wxPGCellRenderer
  66. // -----------------------------------------------------------------------
  67. wxSize wxPGCellRenderer::GetImageSize( const wxPGProperty* WXUNUSED(property),
  68. int WXUNUSED(column),
  69. int WXUNUSED(item) ) const
  70. {
  71. return wxSize(0, 0);
  72. }
  73. void wxPGCellRenderer::DrawText( wxDC& dc, const wxRect& rect,
  74. int xOffset, const wxString& text ) const
  75. {
  76. dc.DrawText( text,
  77. rect.x+xOffset+wxPG_XBEFORETEXT,
  78. rect.y+((rect.height-dc.GetCharHeight())/2) );
  79. }
  80. void wxPGCellRenderer::DrawEditorValue( wxDC& dc, const wxRect& rect,
  81. int xOffset, const wxString& text,
  82. wxPGProperty* property,
  83. const wxPGEditor* editor ) const
  84. {
  85. int yOffset = ((rect.height-dc.GetCharHeight())/2);
  86. if ( editor )
  87. {
  88. wxRect rect2(rect);
  89. rect2.x += xOffset;
  90. rect2.y += yOffset;
  91. rect2.height -= yOffset;
  92. editor->DrawValue( dc, rect2, property, text );
  93. }
  94. else
  95. {
  96. dc.DrawText( text,
  97. rect.x+xOffset+wxPG_XBEFORETEXT,
  98. rect.y+yOffset );
  99. }
  100. }
  101. void wxPGCellRenderer::DrawCaptionSelectionRect( wxDC& dc, int x, int y, int w, int h ) const
  102. {
  103. wxRect focusRect(x,y+((h-dc.GetCharHeight())/2),w,h);
  104. wxPGDrawFocusRect(dc,focusRect);
  105. }
  106. int wxPGCellRenderer::PreDrawCell( wxDC& dc, const wxRect& rect, const wxPGCell& cell, int flags ) const
  107. {
  108. int imageWidth = 0;
  109. // If possible, use cell colours
  110. if ( !(flags & DontUseCellBgCol) )
  111. {
  112. const wxColour& bgCol = cell.GetBgCol();
  113. dc.SetPen(bgCol);
  114. dc.SetBrush(bgCol);
  115. }
  116. if ( !(flags & DontUseCellFgCol) )
  117. {
  118. dc.SetTextForeground(cell.GetFgCol());
  119. }
  120. // Draw Background, but only if not rendering in control
  121. // (as control already has rendered correct background).
  122. if ( !(flags & (Control|ChoicePopup)) )
  123. dc.DrawRectangle(rect);
  124. // Use cell font, if provided
  125. const wxFont& font = cell.GetFont();
  126. if ( font.IsOk() )
  127. dc.SetFont(font);
  128. const wxBitmap& bmp = cell.GetBitmap();
  129. if ( bmp.IsOk() &&
  130. // Do not draw oversized bitmap outside choice popup
  131. ((flags & ChoicePopup) || bmp.GetHeight() < rect.height )
  132. )
  133. {
  134. dc.DrawBitmap( bmp,
  135. rect.x + wxPG_CONTROL_MARGIN + wxCC_CUSTOM_IMAGE_MARGIN1,
  136. rect.y + wxPG_CUSTOM_IMAGE_SPACINGY,
  137. true );
  138. imageWidth = bmp.GetWidth();
  139. }
  140. return imageWidth;
  141. }
  142. void wxPGCellRenderer::PostDrawCell( wxDC& dc,
  143. const wxPropertyGrid* propGrid,
  144. const wxPGCell& cell,
  145. int WXUNUSED(flags) ) const
  146. {
  147. // Revert font
  148. const wxFont& font = cell.GetFont();
  149. if ( font.IsOk() )
  150. dc.SetFont(propGrid->GetFont());
  151. }
  152. // -----------------------------------------------------------------------
  153. // wxPGDefaultRenderer
  154. // -----------------------------------------------------------------------
  155. bool wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect,
  156. const wxPropertyGrid* propertyGrid, wxPGProperty* property,
  157. int column, int item, int flags ) const
  158. {
  159. const wxPGEditor* editor = NULL;
  160. const wxPGCell* cell = NULL;
  161. wxString text;
  162. bool isUnspecified = property->IsValueUnspecified();
  163. if ( column == 1 && item == -1 )
  164. {
  165. int cmnVal = property->GetCommonValue();
  166. if ( cmnVal >= 0 )
  167. {
  168. // Common Value
  169. if ( !isUnspecified )
  170. {
  171. text = propertyGrid->GetCommonValueLabel(cmnVal);
  172. DrawText( dc, rect, 0, text );
  173. if ( !text.empty() )
  174. return true;
  175. }
  176. return false;
  177. }
  178. }
  179. int imageWidth = 0;
  180. int preDrawFlags = flags;
  181. bool res = false;
  182. property->GetDisplayInfo(column, item, flags, &text, &cell);
  183. imageWidth = PreDrawCell( dc, rect, *cell, preDrawFlags );
  184. if ( column == 1 )
  185. {
  186. editor = property->GetColumnEditor(column);
  187. if ( !isUnspecified )
  188. {
  189. // Regular property value
  190. wxSize imageSize = propertyGrid->GetImageSize(property, item);
  191. wxPGPaintData paintdata;
  192. paintdata.m_parent = propertyGrid;
  193. paintdata.m_choiceItem = item;
  194. if ( imageSize.x > 0 )
  195. {
  196. wxRect imageRect(rect.x + wxPG_CONTROL_MARGIN + wxCC_CUSTOM_IMAGE_MARGIN1,
  197. rect.y+wxPG_CUSTOM_IMAGE_SPACINGY,
  198. wxPG_CUSTOM_IMAGE_WIDTH,
  199. rect.height-(wxPG_CUSTOM_IMAGE_SPACINGY*2));
  200. dc.SetPen( wxPen(propertyGrid->GetCellTextColour(), 1, wxSOLID) );
  201. paintdata.m_drawnWidth = imageSize.x;
  202. paintdata.m_drawnHeight = imageSize.y;
  203. property->OnCustomPaint( dc, imageRect, paintdata );
  204. imageWidth = paintdata.m_drawnWidth;
  205. }
  206. text = property->GetValueAsString();
  207. // Add units string?
  208. if ( propertyGrid->GetColumnCount() <= 2 )
  209. {
  210. wxString unitsString = property->GetAttribute(wxPGGlobalVars->m_strUnits, wxEmptyString);
  211. if ( !unitsString.empty() )
  212. text = wxString::Format(wxS("%s %s"), text.c_str(), unitsString.c_str() );
  213. }
  214. }
  215. if ( text.empty() )
  216. {
  217. text = property->GetHintText();
  218. if ( !text.empty() )
  219. {
  220. res = true;
  221. const wxColour& hCol =
  222. propertyGrid->GetCellDisabledTextColour();
  223. dc.SetTextForeground(hCol);
  224. // Must make the editor NULL to override its own rendering
  225. // code.
  226. editor = NULL;
  227. }
  228. }
  229. else
  230. {
  231. res = true;
  232. }
  233. }
  234. int imageOffset = property->GetImageOffset(imageWidth);
  235. DrawEditorValue( dc, rect, imageOffset, text, property, editor );
  236. // active caption gets nice dotted rectangle
  237. if ( property->IsCategory() && column == 0 )
  238. {
  239. if ( flags & Selected )
  240. {
  241. if ( imageOffset > 0 )
  242. {
  243. imageOffset -= DEFAULT_IMAGE_OFFSET_INCREMENT;
  244. imageOffset += wxCC_CUSTOM_IMAGE_MARGIN2 + 4;
  245. }
  246. DrawCaptionSelectionRect( dc,
  247. rect.x+wxPG_XBEFORETEXT-wxPG_CAPRECTXMARGIN+imageOffset,
  248. rect.y-wxPG_CAPRECTYMARGIN+1,
  249. ((wxPropertyCategory*)property)->GetTextExtent(propertyGrid,
  250. propertyGrid->GetCaptionFont())
  251. +(wxPG_CAPRECTXMARGIN*2),
  252. propertyGrid->GetFontHeight()+(wxPG_CAPRECTYMARGIN*2) );
  253. }
  254. }
  255. PostDrawCell(dc, propertyGrid, *cell, preDrawFlags);
  256. return res;
  257. }
  258. wxSize wxPGDefaultRenderer::GetImageSize( const wxPGProperty* property,
  259. int column,
  260. int item ) const
  261. {
  262. if ( property && column == 1 )
  263. {
  264. if ( item == -1 )
  265. {
  266. wxBitmap* bmp = property->GetValueImage();
  267. if ( bmp && bmp->IsOk() )
  268. return wxSize(bmp->GetWidth(),bmp->GetHeight());
  269. }
  270. }
  271. return wxSize(0,0);
  272. }
  273. // -----------------------------------------------------------------------
  274. // wxPGCellData
  275. // -----------------------------------------------------------------------
  276. wxPGCellData::wxPGCellData()
  277. : wxObjectRefData()
  278. {
  279. m_hasValidText = false;
  280. }
  281. // -----------------------------------------------------------------------
  282. // wxPGCell
  283. // -----------------------------------------------------------------------
  284. wxPGCell::wxPGCell()
  285. : wxObject()
  286. {
  287. }
  288. wxPGCell::wxPGCell( const wxString& text,
  289. const wxBitmap& bitmap,
  290. const wxColour& fgCol,
  291. const wxColour& bgCol )
  292. : wxObject()
  293. {
  294. wxPGCellData* data = new wxPGCellData();
  295. m_refData = data;
  296. data->m_text = text;
  297. data->m_bitmap = bitmap;
  298. data->m_fgCol = fgCol;
  299. data->m_bgCol = bgCol;
  300. data->m_hasValidText = true;
  301. }
  302. wxObjectRefData *wxPGCell::CloneRefData( const wxObjectRefData *data ) const
  303. {
  304. wxPGCellData* c = new wxPGCellData();
  305. const wxPGCellData* o = (const wxPGCellData*) data;
  306. c->m_text = o->m_text;
  307. c->m_bitmap = o->m_bitmap;
  308. c->m_fgCol = o->m_fgCol;
  309. c->m_bgCol = o->m_bgCol;
  310. c->m_hasValidText = o->m_hasValidText;
  311. return c;
  312. }
  313. void wxPGCell::SetText( const wxString& text )
  314. {
  315. AllocExclusive();
  316. GetData()->SetText(text);
  317. }
  318. void wxPGCell::SetBitmap( const wxBitmap& bitmap )
  319. {
  320. AllocExclusive();
  321. GetData()->SetBitmap(bitmap);
  322. }
  323. void wxPGCell::SetFgCol( const wxColour& col )
  324. {
  325. AllocExclusive();
  326. GetData()->SetFgCol(col);
  327. }
  328. void wxPGCell::SetFont( const wxFont& font )
  329. {
  330. AllocExclusive();
  331. GetData()->SetFont(font);
  332. }
  333. void wxPGCell::SetBgCol( const wxColour& col )
  334. {
  335. AllocExclusive();
  336. GetData()->SetBgCol(col);
  337. }
  338. void wxPGCell::MergeFrom( const wxPGCell& srcCell )
  339. {
  340. AllocExclusive();
  341. wxPGCellData* data = GetData();
  342. if ( srcCell.HasText() )
  343. data->SetText(srcCell.GetText());
  344. if ( srcCell.GetFgCol().IsOk() )
  345. data->SetFgCol(srcCell.GetFgCol());
  346. if ( srcCell.GetBgCol().IsOk() )
  347. data->SetBgCol(srcCell.GetBgCol());
  348. if ( srcCell.GetBitmap().IsOk() )
  349. data->SetBitmap(srcCell.GetBitmap());
  350. }
  351. void wxPGCell::SetEmptyData()
  352. {
  353. AllocExclusive();
  354. }
  355. // -----------------------------------------------------------------------
  356. // wxPGProperty
  357. // -----------------------------------------------------------------------
  358. IMPLEMENT_ABSTRACT_CLASS(wxPGProperty, wxObject)
  359. wxString* wxPGProperty::sm_wxPG_LABEL = NULL;
  360. void wxPGProperty::Init()
  361. {
  362. m_commonValue = -1;
  363. m_arrIndex = 0xFFFF;
  364. m_parent = NULL;
  365. m_parentState = NULL;
  366. m_clientData = NULL;
  367. m_clientObject = NULL;
  368. m_customEditor = NULL;
  369. #if wxUSE_VALIDATORS
  370. m_validator = NULL;
  371. #endif
  372. m_valueBitmap = NULL;
  373. m_maxLen = 0; // infinite maximum length
  374. m_flags = wxPG_PROP_PROPERTY;
  375. m_depth = 1;
  376. SetExpanded(true);
  377. }
  378. void wxPGProperty::Init( const wxString& label, const wxString& name )
  379. {
  380. // We really need to check if &label and &name are NULL pointers
  381. // (this can if we are called before property grid has been initalized)
  382. if ( (&label) != NULL && label != wxPG_LABEL )
  383. m_label = label;
  384. if ( (&name) != NULL && name != wxPG_LABEL )
  385. DoSetName( name );
  386. else
  387. DoSetName( m_label );
  388. Init();
  389. }
  390. void wxPGProperty::InitAfterAdded( wxPropertyGridPageState* pageState,
  391. wxPropertyGrid* propgrid )
  392. {
  393. //
  394. // Called after property has been added to grid or page
  395. // (so propgrid can be NULL, too).
  396. wxPGProperty* parent = m_parent;
  397. bool parentIsRoot = parent->IsKindOf(wxCLASSINFO(wxPGRootProperty));
  398. //
  399. // Convert invalid cells to default ones in this grid
  400. for ( unsigned int i=0; i<m_cells.size(); i++ )
  401. {
  402. wxPGCell& cell = m_cells[i];
  403. if ( cell.IsInvalid() )
  404. {
  405. const wxPGCell& propDefCell = propgrid->GetPropertyDefaultCell();
  406. const wxPGCell& catDefCell = propgrid->GetCategoryDefaultCell();
  407. if ( !HasFlag(wxPG_PROP_CATEGORY) )
  408. cell = propDefCell;
  409. else
  410. cell = catDefCell;
  411. }
  412. }
  413. m_parentState = pageState;
  414. #if wxPG_COMPATIBILITY_1_4
  415. // Make sure deprecated virtual functions are not implemented
  416. wxString s = GetValueAsString( 0xFFFF );
  417. wxASSERT_MSG( s == g_invalidStringContent,
  418. "Implement ValueToString() instead of GetValueAsString()" );
  419. #endif
  420. if ( !parentIsRoot && !parent->IsCategory() )
  421. {
  422. m_cells = parent->m_cells;
  423. }
  424. // If in hideable adding mode, or if assigned parent is hideable, then
  425. // make this one hideable.
  426. if (
  427. ( !parentIsRoot && parent->HasFlag(wxPG_PROP_HIDDEN) ) ||
  428. ( propgrid && (propgrid->HasInternalFlag(wxPG_FL_ADDING_HIDEABLES)) )
  429. )
  430. SetFlag( wxPG_PROP_HIDDEN );
  431. // Set custom image flag.
  432. int custImgHeight = OnMeasureImage().y;
  433. if ( custImgHeight < 0 )
  434. {
  435. SetFlag(wxPG_PROP_CUSTOMIMAGE);
  436. }
  437. if ( propgrid && (propgrid->HasFlag(wxPG_LIMITED_EDITING)) )
  438. SetFlag(wxPG_PROP_NOEDITOR);
  439. // Make sure parent has some parental flags
  440. if ( !parent->HasFlag(wxPG_PROP_PARENTAL_FLAGS) )
  441. parent->SetParentalType(wxPG_PROP_MISC_PARENT);
  442. if ( !IsCategory() )
  443. {
  444. // This is not a category.
  445. // Depth.
  446. //
  447. unsigned char depth = 1;
  448. if ( !parentIsRoot )
  449. {
  450. depth = parent->m_depth;
  451. if ( !parent->IsCategory() )
  452. depth++;
  453. }
  454. m_depth = depth;
  455. unsigned char greyDepth = depth;
  456. if ( !parentIsRoot )
  457. {
  458. wxPropertyCategory* pc;
  459. if ( parent->IsCategory() )
  460. pc = (wxPropertyCategory* ) parent;
  461. else
  462. // This conditional compile is necessary to
  463. // bypass some compiler bug.
  464. pc = pageState->GetPropertyCategory(parent);
  465. if ( pc )
  466. greyDepth = pc->GetDepth();
  467. else
  468. greyDepth = parent->m_depthBgCol;
  469. }
  470. m_depthBgCol = greyDepth;
  471. }
  472. else
  473. {
  474. // This is a category.
  475. // depth
  476. unsigned char depth = 1;
  477. if ( !parentIsRoot )
  478. {
  479. depth = parent->m_depth + 1;
  480. }
  481. m_depth = depth;
  482. m_depthBgCol = depth;
  483. }
  484. //
  485. // Has initial children
  486. if ( GetChildCount() )
  487. {
  488. // Check parental flags
  489. wxASSERT_MSG( ((m_flags & wxPG_PROP_PARENTAL_FLAGS) ==
  490. wxPG_PROP_AGGREGATE) ||
  491. ((m_flags & wxPG_PROP_PARENTAL_FLAGS) ==
  492. wxPG_PROP_MISC_PARENT),
  493. "wxPGProperty parental flags set incorrectly at "
  494. "this time" );
  495. if ( HasFlag(wxPG_PROP_AGGREGATE) )
  496. {
  497. // Properties with private children are not expanded by default.
  498. SetExpanded(false);
  499. }
  500. else if ( propgrid && propgrid->HasFlag(wxPG_HIDE_MARGIN) )
  501. {
  502. // ...unless it cannot be expanded by user and therefore must
  503. // remain visible at all times
  504. SetExpanded(true);
  505. }
  506. //
  507. // Prepare children recursively
  508. for ( unsigned int i=0; i<GetChildCount(); i++ )
  509. {
  510. wxPGProperty* child = Item(i);
  511. child->InitAfterAdded(pageState, pageState->GetGrid());
  512. }
  513. if ( propgrid && (propgrid->GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES) )
  514. SetFlagRecursively(wxPG_PROP_AUTO_UNSPECIFIED, true);
  515. }
  516. }
  517. void wxPGProperty::OnDetached(wxPropertyGridPageState* WXUNUSED(state),
  518. wxPropertyGrid* propgrid)
  519. {
  520. if ( propgrid )
  521. {
  522. const wxPGCell& propDefCell = propgrid->GetPropertyDefaultCell();
  523. const wxPGCell& catDefCell = propgrid->GetCategoryDefaultCell();
  524. // Make default cells invalid
  525. for ( unsigned int i=0; i<m_cells.size(); i++ )
  526. {
  527. wxPGCell& cell = m_cells[i];
  528. if ( cell.IsSameAs(propDefCell) ||
  529. cell.IsSameAs(catDefCell) )
  530. {
  531. cell.UnRef();
  532. }
  533. }
  534. }
  535. }
  536. wxPGProperty::wxPGProperty()
  537. : wxObject()
  538. {
  539. Init();
  540. }
  541. wxPGProperty::wxPGProperty( const wxString& label, const wxString& name )
  542. : wxObject()
  543. {
  544. Init( label, name );
  545. }
  546. wxPGProperty::~wxPGProperty()
  547. {
  548. delete m_clientObject;
  549. Empty(); // this deletes items
  550. delete m_valueBitmap;
  551. #if wxUSE_VALIDATORS
  552. delete m_validator;
  553. #endif
  554. // This makes it easier for us to detect dangling pointers
  555. m_parent = NULL;
  556. }
  557. bool wxPGProperty::IsSomeParent( wxPGProperty* candidate ) const
  558. {
  559. wxPGProperty* parent = m_parent;
  560. do
  561. {
  562. if ( parent == candidate )
  563. return true;
  564. parent = parent->m_parent;
  565. } while ( parent );
  566. return false;
  567. }
  568. void wxPGProperty::SetName( const wxString& newName )
  569. {
  570. wxPropertyGrid* pg = GetGrid();
  571. if ( pg )
  572. pg->SetPropertyName(this, newName);
  573. else
  574. DoSetName(newName);
  575. }
  576. wxString wxPGProperty::GetName() const
  577. {
  578. wxPGProperty* parent = GetParent();
  579. if ( m_name.empty() || !parent || parent->IsCategory() || parent->IsRoot() )
  580. return m_name;
  581. return m_parent->GetName() + wxS(".") + m_name;
  582. }
  583. wxPropertyGrid* wxPGProperty::GetGrid() const
  584. {
  585. if ( !m_parentState )
  586. return NULL;
  587. return m_parentState->GetGrid();
  588. }
  589. int wxPGProperty::Index( const wxPGProperty* p ) const
  590. {
  591. return wxPGFindInVector(m_children, p);
  592. }
  593. bool wxPGProperty::ValidateValue( wxVariant& WXUNUSED(value), wxPGValidationInfo& WXUNUSED(validationInfo) ) const
  594. {
  595. return true;
  596. }
  597. void wxPGProperty::OnSetValue()
  598. {
  599. }
  600. void wxPGProperty::RefreshChildren ()
  601. {
  602. }
  603. void wxPGProperty::OnValidationFailure( wxVariant& WXUNUSED(pendingValue) )
  604. {
  605. }
  606. void wxPGProperty::GetDisplayInfo( unsigned int column,
  607. int choiceIndex,
  608. int flags,
  609. wxString* pString,
  610. const wxPGCell** pCell )
  611. {
  612. const wxPGCell* cell = NULL;
  613. if ( !(flags & wxPGCellRenderer::ChoicePopup) )
  614. {
  615. // Not painting list of choice popups, so get text from property
  616. if ( column != 1 || !IsValueUnspecified() || IsCategory() )
  617. {
  618. cell = &GetCell(column);
  619. }
  620. else
  621. {
  622. // Use special unspecified value cell
  623. cell = &GetGrid()->GetUnspecifiedValueAppearance();
  624. }
  625. if ( cell->HasText() )
  626. {
  627. *pString = cell->GetText();
  628. }
  629. else
  630. {
  631. if ( column == 0 )
  632. *pString = GetLabel();
  633. else if ( column == 1 )
  634. *pString = GetDisplayedString();
  635. else if ( column == 2 )
  636. *pString = GetAttribute(wxPGGlobalVars->m_strUnits, wxEmptyString);
  637. }
  638. }
  639. else
  640. {
  641. wxASSERT( column == 1 );
  642. if ( choiceIndex != wxNOT_FOUND )
  643. {
  644. const wxPGChoiceEntry& entry = m_choices[choiceIndex];
  645. if ( entry.GetBitmap().IsOk() ||
  646. entry.GetFgCol().IsOk() ||
  647. entry.GetBgCol().IsOk() )
  648. cell = &entry;
  649. *pString = m_choices.GetLabel(choiceIndex);
  650. }
  651. }
  652. if ( !cell )
  653. cell = &GetCell(column);
  654. wxASSERT_MSG( cell->GetData(),
  655. wxString::Format("Invalid cell for property %s",
  656. GetName().c_str()) );
  657. *pCell = cell;
  658. }
  659. /*
  660. wxString wxPGProperty::GetColumnText( unsigned int col, int choiceIndex ) const
  661. {
  662. if ( col != 1 || choiceIndex == wxNOT_FOUND )
  663. {
  664. const wxPGCell& cell = GetCell(col);
  665. if ( cell->HasText() )
  666. {
  667. return cell->GetText();
  668. }
  669. else
  670. {
  671. if ( col == 0 )
  672. return GetLabel();
  673. else if ( col == 1 )
  674. return GetDisplayedString();
  675. else if ( col == 2 )
  676. return GetAttribute(wxPGGlobalVars->m_strUnits, wxEmptyString);
  677. }
  678. }
  679. else
  680. {
  681. // Use choice
  682. return m_choices.GetLabel(choiceIndex);
  683. }
  684. return wxEmptyString;
  685. }
  686. */
  687. void wxPGProperty::DoGenerateComposedValue( wxString& text,
  688. int argFlags,
  689. const wxVariantList* valueOverrides,
  690. wxPGHashMapS2S* childResults ) const
  691. {
  692. int i;
  693. int iMax = m_children.size();
  694. text.clear();
  695. if ( iMax == 0 )
  696. return;
  697. if ( iMax > PWC_CHILD_SUMMARY_LIMIT &&
  698. !(argFlags & wxPG_FULL_VALUE) )
  699. iMax = PWC_CHILD_SUMMARY_LIMIT;
  700. int iMaxMinusOne = iMax-1;
  701. if ( !IsTextEditable() )
  702. argFlags |= wxPG_UNEDITABLE_COMPOSITE_FRAGMENT;
  703. wxPGProperty* curChild = m_children[0];
  704. bool overridesLeft = false;
  705. wxVariant overrideValue;
  706. wxVariantList::const_iterator node;
  707. if ( valueOverrides )
  708. {
  709. node = valueOverrides->begin();
  710. if ( node != valueOverrides->end() )
  711. {
  712. overrideValue = *node;
  713. overridesLeft = true;
  714. }
  715. }
  716. for ( i = 0; i < iMax; i++ )
  717. {
  718. wxVariant childValue;
  719. wxString childLabel = curChild->GetLabel();
  720. // Check for value override
  721. if ( overridesLeft && overrideValue.GetName() == childLabel )
  722. {
  723. if ( !overrideValue.IsNull() )
  724. childValue = overrideValue;
  725. else
  726. childValue = curChild->GetValue();
  727. ++node;
  728. if ( node != valueOverrides->end() )
  729. overrideValue = *node;
  730. else
  731. overridesLeft = false;
  732. }
  733. else
  734. {
  735. childValue = curChild->GetValue();
  736. }
  737. wxString s;
  738. if ( !childValue.IsNull() )
  739. {
  740. if ( overridesLeft &&
  741. curChild->HasFlag(wxPG_PROP_COMPOSED_VALUE) &&
  742. childValue.GetType() == wxPG_VARIANT_TYPE_LIST )
  743. {
  744. wxVariantList& childList = childValue.GetList();
  745. DoGenerateComposedValue(s, argFlags|wxPG_COMPOSITE_FRAGMENT,
  746. &childList, childResults);
  747. }
  748. else
  749. {
  750. s = curChild->ValueToString(childValue,
  751. argFlags|wxPG_COMPOSITE_FRAGMENT);
  752. }
  753. }
  754. if ( childResults && curChild->GetChildCount() )
  755. (*childResults)[curChild->GetName()] = s;
  756. bool skip = false;
  757. if ( (argFlags & wxPG_UNEDITABLE_COMPOSITE_FRAGMENT) && s.empty() )
  758. skip = true;
  759. if ( !curChild->GetChildCount() || skip )
  760. text += s;
  761. else
  762. text += wxS("[") + s + wxS("]");
  763. if ( i < iMaxMinusOne )
  764. {
  765. if ( text.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT &&
  766. !(argFlags & wxPG_EDITABLE_VALUE) &&
  767. !(argFlags & wxPG_FULL_VALUE) )
  768. break;
  769. if ( !skip )
  770. {
  771. if ( !curChild->GetChildCount() )
  772. text += wxS("; ");
  773. else
  774. text += wxS(" ");
  775. }
  776. curChild = m_children[i+1];
  777. }
  778. }
  779. if ( (unsigned int)i < m_children.size() )
  780. {
  781. if ( !text.EndsWith(wxS("; ")) )
  782. text += wxS("; ...");
  783. else
  784. text += wxS("...");
  785. }
  786. }
  787. wxString wxPGProperty::ValueToString( wxVariant& WXUNUSED(value),
  788. int argFlags ) const
  789. {
  790. wxCHECK_MSG( GetChildCount() > 0,
  791. wxString(),
  792. "If user property does not have any children, it must "
  793. "override GetValueAsString" );
  794. // FIXME: Currently code below only works if value is actually m_value
  795. wxASSERT_MSG( argFlags & wxPG_VALUE_IS_CURRENT,
  796. "Sorry, currently default wxPGProperty::ValueToString() "
  797. "implementation only works if value is m_value." );
  798. wxString text;
  799. DoGenerateComposedValue(text, argFlags);
  800. return text;
  801. }
  802. wxString wxPGProperty::GetValueAsString( int argFlags ) const
  803. {
  804. #if wxPG_COMPATIBILITY_1_4
  805. // This is backwards compatibility test
  806. // That is, to make sure this function is not overridden
  807. // (instead, ValueToString() should be).
  808. if ( argFlags == 0xFFFF )
  809. {
  810. // Do not override! (for backwards compliancy)
  811. return g_invalidStringContent;
  812. }
  813. #endif
  814. wxPropertyGrid* pg = GetGrid();
  815. if ( IsValueUnspecified() )
  816. return pg->GetUnspecifiedValueText(argFlags);
  817. if ( m_commonValue == -1 )
  818. {
  819. wxVariant value(GetValue());
  820. return ValueToString(value, argFlags|wxPG_VALUE_IS_CURRENT);
  821. }
  822. //
  823. // Return common value's string representation
  824. const wxPGCommonValue* cv = pg->GetCommonValue(m_commonValue);
  825. if ( argFlags & wxPG_FULL_VALUE )
  826. {
  827. return cv->GetLabel();
  828. }
  829. else if ( argFlags & wxPG_EDITABLE_VALUE )
  830. {
  831. return cv->GetEditableText();
  832. }
  833. else
  834. {
  835. return cv->GetLabel();
  836. }
  837. }
  838. wxString wxPGProperty::GetValueString( int argFlags ) const
  839. {
  840. return GetValueAsString(argFlags);
  841. }
  842. bool wxPGProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
  843. {
  844. variant = (long)number;
  845. return true;
  846. }
  847. // Convert semicolon delimited tokens into child values.
  848. bool wxPGProperty::StringToValue( wxVariant& v, const wxString& text, int argFlags ) const
  849. {
  850. if ( !GetChildCount() )
  851. return false;
  852. unsigned int curChild = 0;
  853. unsigned int iMax = m_children.size();
  854. if ( iMax > PWC_CHILD_SUMMARY_LIMIT &&
  855. !(argFlags & wxPG_FULL_VALUE) )
  856. iMax = PWC_CHILD_SUMMARY_LIMIT;
  857. bool changed = false;
  858. wxString token;
  859. size_t pos = 0;
  860. // Its best only to add non-empty group items
  861. bool addOnlyIfNotEmpty = false;
  862. const wxChar delimeter = wxS(';');
  863. size_t tokenStart = 0xFFFFFF;
  864. wxVariantList temp_list;
  865. wxVariant list(temp_list);
  866. int propagatedFlags = argFlags & (wxPG_REPORT_ERROR|wxPG_PROGRAMMATIC_VALUE);
  867. wxLogTrace("propgrid",
  868. wxT(">> %s.StringToValue('%s')"), GetLabel(), text);
  869. wxString::const_iterator it = text.begin();
  870. wxUniChar a;
  871. if ( it != text.end() )
  872. a = *it;
  873. else
  874. a = 0;
  875. for ( ;; )
  876. {
  877. // How many units we iterate string forward at the end of loop?
  878. // We need to keep track of this or risk going to negative
  879. // with it-- operation.
  880. unsigned int strPosIncrement = 1;
  881. if ( tokenStart != 0xFFFFFF )
  882. {
  883. // Token is running
  884. if ( a == delimeter || a == 0 )
  885. {
  886. token = text.substr(tokenStart,pos-tokenStart);
  887. token.Trim(true);
  888. size_t len = token.length();
  889. if ( !addOnlyIfNotEmpty || len > 0 )
  890. {
  891. const wxPGProperty* child = Item(curChild);
  892. wxVariant variant(child->GetValue());
  893. wxString childName = child->GetBaseName();
  894. wxLogTrace("propgrid",
  895. wxT("token = '%s', child = %s"),
  896. token, childName);
  897. // Add only if editable or setting programmatically
  898. if ( (argFlags & wxPG_PROGRAMMATIC_VALUE) ||
  899. (!child->HasFlag(wxPG_PROP_DISABLED) &&
  900. !child->HasFlag(wxPG_PROP_READONLY)) )
  901. {
  902. if ( len > 0 )
  903. {
  904. if ( child->StringToValue(variant, token,
  905. propagatedFlags|wxPG_COMPOSITE_FRAGMENT) )
  906. {
  907. // We really need to set the variant's name
  908. // *after* child->StringToValue() has been
  909. // called, since variant's value may be set by
  910. // assigning another variant into it, which
  911. // then usually causes name to be copied (ie.
  912. // usually cleared) as well. wxBoolProperty
  913. // being case in point with its use of
  914. // wxPGVariant_Bool macro as an optimization.
  915. variant.SetName(childName);
  916. list.Append(variant);
  917. changed = true;
  918. }
  919. }
  920. else
  921. {
  922. // Empty, becomes unspecified
  923. variant.MakeNull();
  924. variant.SetName(childName);
  925. list.Append(variant);
  926. changed = true;
  927. }
  928. }
  929. curChild++;
  930. if ( curChild >= iMax )
  931. break;
  932. }
  933. tokenStart = 0xFFFFFF;
  934. }
  935. }
  936. else
  937. {
  938. // Token is not running
  939. if ( a != wxS(' ') )
  940. {
  941. addOnlyIfNotEmpty = false;
  942. // Is this a group of tokens?
  943. if ( a == wxS('[') )
  944. {
  945. int depth = 1;
  946. if ( it != text.end() ) ++it;
  947. pos++;
  948. size_t startPos = pos;
  949. // Group item - find end
  950. while ( it != text.end() && depth > 0 )
  951. {
  952. a = *it;
  953. ++it;
  954. pos++;
  955. if ( a == wxS(']') )
  956. depth--;
  957. else if ( a == wxS('[') )
  958. depth++;
  959. }
  960. token = text.substr(startPos,pos-startPos-1);
  961. if ( token.empty() )
  962. break;
  963. const wxPGProperty* child = Item(curChild);
  964. wxVariant oldChildValue = child->GetValue();
  965. wxVariant variant(oldChildValue);
  966. if ( (argFlags & wxPG_PROGRAMMATIC_VALUE) ||
  967. (!child->HasFlag(wxPG_PROP_DISABLED) &&
  968. !child->HasFlag(wxPG_PROP_READONLY)) )
  969. {
  970. wxString childName = child->GetBaseName();
  971. bool stvRes = child->StringToValue( variant, token,
  972. propagatedFlags );
  973. if ( stvRes || (variant != oldChildValue) )
  974. {
  975. variant.SetName(childName);
  976. list.Append(variant);
  977. changed = true;
  978. }
  979. else
  980. {
  981. // No changes...
  982. }
  983. }
  984. curChild++;
  985. if ( curChild >= iMax )
  986. break;
  987. addOnlyIfNotEmpty = true;
  988. tokenStart = 0xFFFFFF;
  989. }
  990. else
  991. {
  992. tokenStart = pos;
  993. if ( a == delimeter )
  994. strPosIncrement -= 1;
  995. }
  996. }
  997. }
  998. if ( a == 0 )
  999. break;
  1000. it += strPosIncrement;
  1001. if ( it != text.end() )
  1002. {
  1003. a = *it;
  1004. }
  1005. else
  1006. {
  1007. a = 0;
  1008. }
  1009. pos += strPosIncrement;
  1010. }
  1011. if ( changed )
  1012. v = list;
  1013. return changed;
  1014. }
  1015. bool wxPGProperty::SetValueFromString( const wxString& text, int argFlags )
  1016. {
  1017. wxVariant variant(m_value);
  1018. bool res = StringToValue(variant, text, argFlags);
  1019. if ( res )
  1020. SetValue(variant);
  1021. return res;
  1022. }
  1023. bool wxPGProperty::SetValueFromInt( long number, int argFlags )
  1024. {
  1025. wxVariant variant(m_value);
  1026. bool res = IntToValue(variant, number, argFlags);
  1027. if ( res )
  1028. SetValue(variant);
  1029. return res;
  1030. }
  1031. wxSize wxPGProperty::OnMeasureImage( int WXUNUSED(item) ) const
  1032. {
  1033. if ( m_valueBitmap )
  1034. return wxSize(m_valueBitmap->GetWidth(),-1);
  1035. return wxSize(0,0);
  1036. }
  1037. int wxPGProperty::GetImageOffset( int imageWidth ) const
  1038. {
  1039. int imageOffset = 0;
  1040. if ( imageWidth )
  1041. {
  1042. // Do not increment offset too much for wide images
  1043. if ( imageWidth <= (wxPG_CUSTOM_IMAGE_WIDTH+5) )
  1044. imageOffset = imageWidth + DEFAULT_IMAGE_OFFSET_INCREMENT;
  1045. else
  1046. imageOffset = imageWidth + 1;
  1047. }
  1048. return imageOffset;
  1049. }
  1050. wxPGCellRenderer* wxPGProperty::GetCellRenderer( int WXUNUSED(column) ) const
  1051. {
  1052. return wxPGGlobalVars->m_defaultRenderer;
  1053. }
  1054. void wxPGProperty::OnCustomPaint( wxDC& dc,
  1055. const wxRect& rect,
  1056. wxPGPaintData& )
  1057. {
  1058. wxBitmap* bmp = m_valueBitmap;
  1059. wxCHECK_RET( bmp && bmp->IsOk(), wxT("invalid bitmap") );
  1060. wxCHECK_RET( rect.x >= 0, wxT("unexpected measure call") );
  1061. dc.DrawBitmap(*bmp,rect.x,rect.y);
  1062. }
  1063. const wxPGEditor* wxPGProperty::DoGetEditorClass() const
  1064. {
  1065. return wxPGEditor_TextCtrl;
  1066. }
  1067. // Default extra property event handling - that is, none at all.
  1068. bool wxPGProperty::OnEvent( wxPropertyGrid*, wxWindow*, wxEvent& )
  1069. {
  1070. return false;
  1071. }
  1072. void wxPGProperty::SetValue( wxVariant value, wxVariant* pList, int flags )
  1073. {
  1074. // If auto unspecified values are not wanted (via window or property style),
  1075. // then get default value instead of wxNullVariant.
  1076. if ( value.IsNull() && (flags & wxPG_SETVAL_BY_USER) &&
  1077. !UsesAutoUnspecified() )
  1078. {
  1079. value = GetDefaultValue();
  1080. }
  1081. if ( !value.IsNull() )
  1082. {
  1083. wxVariant tempListVariant;
  1084. SetCommonValue(-1);
  1085. // List variants are reserved a special purpose
  1086. // as intermediate containers for child values
  1087. // of properties with children.
  1088. if ( value.GetType() == wxPG_VARIANT_TYPE_LIST )
  1089. {
  1090. //
  1091. // However, situation is different for composed string properties
  1092. if ( HasFlag(wxPG_PROP_COMPOSED_VALUE) )
  1093. {
  1094. tempListVariant = value;
  1095. pList = &tempListVariant;
  1096. }
  1097. wxVariant newValue;
  1098. AdaptListToValue(value, &newValue);
  1099. value = newValue;
  1100. //wxLogDebug(wxT(">> %s.SetValue() adapted list value to type '%s'"),GetName().c_str(),value.GetType().c_str());
  1101. }
  1102. if ( HasFlag( wxPG_PROP_AGGREGATE) )
  1103. flags |= wxPG_SETVAL_AGGREGATED;
  1104. if ( pList && !pList->IsNull() )
  1105. {
  1106. wxASSERT( pList->GetType() == wxPG_VARIANT_TYPE_LIST );
  1107. wxASSERT( GetChildCount() );
  1108. wxASSERT( !IsCategory() );
  1109. wxVariantList& list = pList->GetList();
  1110. wxVariantList::iterator node;
  1111. unsigned int i = 0;
  1112. //wxLogDebug(wxT(">> %s.SetValue() pList parsing"),GetName().c_str());
  1113. // Children in list can be in any order, but we will give hint to
  1114. // GetPropertyByNameWH(). This optimizes for full list parsing.
  1115. for ( node = list.begin(); node != list.end(); ++node )
  1116. {
  1117. wxVariant& childValue = *((wxVariant*)*node);
  1118. wxPGProperty* child = GetPropertyByNameWH(childValue.GetName(), i);
  1119. if ( child )
  1120. {
  1121. //wxLogDebug(wxT("%i: child = %s, childValue.GetType()=%s"),i,child->GetBaseName().c_str(),childValue.GetType().c_str());
  1122. if ( childValue.GetType() == wxPG_VARIANT_TYPE_LIST )
  1123. {
  1124. if ( child->HasFlag(wxPG_PROP_AGGREGATE) && !(flags & wxPG_SETVAL_AGGREGATED) )
  1125. {
  1126. wxVariant listRefCopy = childValue;
  1127. child->SetValue(childValue, &listRefCopy, flags|wxPG_SETVAL_FROM_PARENT);
  1128. }
  1129. else
  1130. {
  1131. wxVariant oldVal = child->GetValue();
  1132. child->SetValue(oldVal, &childValue, flags|wxPG_SETVAL_FROM_PARENT);
  1133. }
  1134. }
  1135. else if ( child->GetValue() != childValue )
  1136. {
  1137. // For aggregate properties, we will trust RefreshChildren()
  1138. // to update child values.
  1139. if ( !HasFlag(wxPG_PROP_AGGREGATE) )
  1140. child->SetValue(childValue, NULL, flags|wxPG_SETVAL_FROM_PARENT);
  1141. if ( flags & wxPG_SETVAL_BY_USER )
  1142. child->SetFlag(wxPG_PROP_MODIFIED);
  1143. }
  1144. }
  1145. i++;
  1146. }
  1147. // Always call OnSetValue() for a parent property (do not call it
  1148. // here if the value is non-null because it will then be called
  1149. // below)
  1150. if ( value.IsNull() )
  1151. OnSetValue();
  1152. }
  1153. if ( !value.IsNull() )
  1154. {
  1155. m_value = value;
  1156. OnSetValue();
  1157. }
  1158. if ( flags & wxPG_SETVAL_BY_USER )
  1159. SetFlag(wxPG_PROP_MODIFIED);
  1160. if ( HasFlag(wxPG_PROP_AGGREGATE) )
  1161. RefreshChildren();
  1162. }
  1163. else
  1164. {
  1165. if ( m_commonValue != -1 )
  1166. {
  1167. wxPropertyGrid* pg = GetGrid();
  1168. if ( !pg || m_commonValue != pg->GetUnspecifiedCommonValue() )
  1169. SetCommonValue(-1);
  1170. }
  1171. m_value = value;
  1172. // Set children to unspecified, but only if aggregate or
  1173. // value is <composed>
  1174. if ( AreChildrenComponents() )
  1175. {
  1176. unsigned int i;
  1177. for ( i=0; i<GetChildCount(); i++ )
  1178. Item(i)->SetValue(value, NULL, flags|wxPG_SETVAL_FROM_PARENT);
  1179. }
  1180. }
  1181. if ( !(flags & wxPG_SETVAL_FROM_PARENT) )
  1182. UpdateParentValues();
  1183. //
  1184. // Update editor control.
  1185. if ( flags & wxPG_SETVAL_REFRESH_EDITOR )
  1186. {
  1187. wxPropertyGrid* pg = GetGridIfDisplayed();
  1188. if ( pg )
  1189. {
  1190. wxPGProperty* selected = pg->GetSelectedProperty();
  1191. // Only refresh the control if this was selected, or
  1192. // this was some parent of selected, or vice versa)
  1193. if ( selected && (selected == this ||
  1194. selected->IsSomeParent(this) ||
  1195. this->IsSomeParent(selected)) )
  1196. RefreshEditor();
  1197. pg->DrawItemAndValueRelated(this);
  1198. }
  1199. }
  1200. }
  1201. void wxPGProperty::SetValueInEvent( wxVariant value ) const
  1202. {
  1203. GetGrid()->ValueChangeInEvent(value);
  1204. }
  1205. void wxPGProperty::SetFlagRecursively( wxPGPropertyFlags flag, bool set )
  1206. {
  1207. ChangeFlag(flag, set);
  1208. unsigned int i;
  1209. for ( i = 0; i < GetChildCount(); i++ )
  1210. Item(i)->SetFlagRecursively(flag, set);
  1211. }
  1212. void wxPGProperty::RefreshEditor()
  1213. {
  1214. if ( !m_parent )
  1215. return;
  1216. wxPropertyGrid* pg = GetGrid();
  1217. if ( pg && pg->GetSelectedProperty() == this )
  1218. pg->RefreshEditor();
  1219. }
  1220. wxVariant wxPGProperty::GetDefaultValue() const
  1221. {
  1222. wxVariant defVal = GetAttribute(wxPG_ATTR_DEFAULT_VALUE);
  1223. if ( !defVal.IsNull() )
  1224. return defVal;
  1225. wxVariant value = GetValue();
  1226. if ( !value.IsNull() )
  1227. {
  1228. wxString valueType(value.GetType());
  1229. if ( valueType == wxPG_VARIANT_TYPE_LONG )
  1230. return wxPGVariant_Zero;
  1231. if ( valueType == wxPG_VARIANT_TYPE_STRING )
  1232. return wxPGVariant_EmptyString;
  1233. if ( valueType == wxPG_VARIANT_TYPE_BOOL )
  1234. return wxPGVariant_False;
  1235. if ( valueType == wxPG_VARIANT_TYPE_DOUBLE )
  1236. return wxVariant(0.0);
  1237. if ( valueType == wxPG_VARIANT_TYPE_ARRSTRING )
  1238. return wxVariant(wxArrayString());
  1239. if ( valueType == wxS("wxLongLong") )
  1240. return WXVARIANT(wxLongLong(0));
  1241. if ( valueType == wxS("wxULongLong") )
  1242. return WXVARIANT(wxULongLong(0));
  1243. if ( valueType == wxS("wxColour") )
  1244. return WXVARIANT(*wxBLACK);
  1245. #if wxUSE_DATETIME
  1246. if ( valueType == wxPG_VARIANT_TYPE_DATETIME )
  1247. return wxVariant(wxDateTime::Now());
  1248. #endif
  1249. if ( valueType == wxS("wxFont") )
  1250. return WXVARIANT(*wxNORMAL_FONT);
  1251. if ( valueType == wxS("wxPoint") )
  1252. return WXVARIANT(wxPoint(0, 0));
  1253. if ( valueType == wxS("wxSize") )
  1254. return WXVARIANT(wxSize(0, 0));
  1255. }
  1256. return wxVariant();
  1257. }
  1258. void wxPGProperty::Enable( bool enable )
  1259. {
  1260. wxPropertyGrid* pg = GetGrid();
  1261. // Preferably call the version in the owning wxPropertyGrid,
  1262. // since it handles the editor de-activation.
  1263. if ( pg )
  1264. pg->EnableProperty(this, enable);
  1265. else
  1266. DoEnable(enable);
  1267. }
  1268. void wxPGProperty::DoEnable( bool enable )
  1269. {
  1270. if ( enable )
  1271. ClearFlag(wxPG_PROP_DISABLED);
  1272. else
  1273. SetFlag(wxPG_PROP_DISABLED);
  1274. // Apply same to sub-properties as well
  1275. unsigned int i;
  1276. for ( i = 0; i < GetChildCount(); i++ )
  1277. Item(i)->DoEnable( enable );
  1278. }
  1279. void wxPGProperty::EnsureCells( unsigned int column )
  1280. {
  1281. if ( column >= m_cells.size() )
  1282. {
  1283. // Fill empty slots with default cells
  1284. wxPropertyGrid* pg = GetGrid();
  1285. wxPGCell defaultCell;
  1286. if ( pg )
  1287. {
  1288. // Work around possible VC6 bug by using intermediate variables
  1289. const wxPGCell& propDefCell = pg->GetPropertyDefaultCell();
  1290. const wxPGCell& catDefCell = pg->GetCategoryDefaultCell();
  1291. if ( !HasFlag(wxPG_PROP_CATEGORY) )
  1292. defaultCell = propDefCell;
  1293. else
  1294. defaultCell = catDefCell;
  1295. }
  1296. // TODO: Replace with resize() call
  1297. unsigned int cellCountMax = column+1;
  1298. for ( unsigned int i=m_cells.size(); i<cellCountMax; i++ )
  1299. m_cells.push_back(defaultCell);
  1300. }
  1301. }
  1302. void wxPGProperty::SetCell( int column,
  1303. const wxPGCell& cell )
  1304. {
  1305. EnsureCells(column);
  1306. m_cells[column] = cell;
  1307. }
  1308. void wxPGProperty::AdaptiveSetCell( unsigned int firstCol,
  1309. unsigned int lastCol,
  1310. const wxPGCell& cell,
  1311. const wxPGCell& srcData,
  1312. wxPGCellData* unmodCellData,
  1313. FlagType ignoreWithFlags,
  1314. bool recursively )
  1315. {
  1316. //
  1317. // Sets cell in memory optimizing fashion. That is, if
  1318. // current cell data matches unmodCellData, we will
  1319. // simply get reference to data from cell. Otherwise,
  1320. // cell information from srcData is merged into current.
  1321. //
  1322. if ( !(m_flags & ignoreWithFlags) && !IsRoot() )
  1323. {
  1324. EnsureCells(lastCol);
  1325. for ( unsigned int col=firstCol; col<=lastCol; col++ )
  1326. {
  1327. if ( m_cells[col].GetData() == unmodCellData )
  1328. {
  1329. // Data matches... use cell directly
  1330. m_cells[col] = cell;
  1331. }
  1332. else
  1333. {
  1334. // Data did not match... merge valid information
  1335. m_cells[col].MergeFrom(srcData);
  1336. }
  1337. }
  1338. }
  1339. if ( recursively )
  1340. {
  1341. for ( unsigned int i=0; i<GetChildCount(); i++ )
  1342. Item(i)->AdaptiveSetCell( firstCol,
  1343. lastCol,
  1344. cell,
  1345. srcData,
  1346. unmodCellData,
  1347. ignoreWithFlags,
  1348. recursively );
  1349. }
  1350. }
  1351. const wxPGCell& wxPGProperty::GetCell( unsigned int column ) const
  1352. {
  1353. if ( m_cells.size() > column )
  1354. return m_cells[column];
  1355. wxPropertyGrid* pg = GetGrid();
  1356. if ( IsCategory() )
  1357. return pg->GetCategoryDefaultCell();
  1358. return pg->GetPropertyDefaultCell();
  1359. }
  1360. wxPGCell& wxPGProperty::GetOrCreateCell( unsigned int column )
  1361. {
  1362. EnsureCells(column);
  1363. return m_cells[column];
  1364. }
  1365. void wxPGProperty::SetBackgroundColour( const wxColour& colour,
  1366. int flags )
  1367. {
  1368. wxPGProperty* firstProp = this;
  1369. bool recursively = flags & wxPG_RECURSE ? true : false;
  1370. //
  1371. // If category is tried to set recursively, skip it and only
  1372. // affect the children.
  1373. if ( recursively )
  1374. {
  1375. while ( firstProp->IsCategory() )
  1376. {
  1377. if ( !firstProp->GetChildCount() )
  1378. return;
  1379. firstProp = firstProp->Item(0);
  1380. }
  1381. }
  1382. wxPGCell& firstCell = firstProp->GetCell(0);
  1383. wxPGCellData* firstCellData = firstCell.GetData();
  1384. wxPGCell newCell(firstCell);
  1385. newCell.SetBgCol(colour);
  1386. wxPGCell srcCell;
  1387. srcCell.SetBgCol(colour);
  1388. AdaptiveSetCell( 0,
  1389. GetParentState()->GetColumnCount()-1,
  1390. newCell,
  1391. srcCell,
  1392. firstCellData,
  1393. recursively ? wxPG_PROP_CATEGORY : 0,
  1394. recursively );
  1395. }
  1396. void wxPGProperty::SetTextColour( const wxColour& colour,
  1397. int flags )
  1398. {
  1399. wxPGProperty* firstProp = this;
  1400. bool recursively = flags & wxPG_RECURSE ? true : false;
  1401. //
  1402. // If category is tried to set recursively, skip it and only
  1403. // affect the children.
  1404. if ( recursively )
  1405. {
  1406. while ( firstProp->IsCategory() )
  1407. {
  1408. if ( !firstProp->GetChildCount() )
  1409. return;
  1410. firstProp = firstProp->Item(0);
  1411. }
  1412. }
  1413. wxPGCell& firstCell = firstProp->GetCell(0);
  1414. wxPGCellData* firstCellData = firstCell.GetData();
  1415. wxPGCell newCell(firstCell);
  1416. newCell.SetFgCol(colour);
  1417. wxPGCell srcCell;
  1418. srcCell.SetFgCol(colour);
  1419. AdaptiveSetCell( 0,
  1420. GetParentState()->GetColumnCount()-1,
  1421. newCell,
  1422. srcCell,
  1423. firstCellData,
  1424. recursively ? wxPG_PROP_CATEGORY : 0,
  1425. recursively );
  1426. }
  1427. wxPGEditorDialogAdapter* wxPGProperty::GetEditorDialog() const
  1428. {
  1429. return NULL;
  1430. }
  1431. bool wxPGProperty::DoSetAttribute( const wxString& WXUNUSED(name), wxVariant& WXUNUSED(value) )
  1432. {
  1433. return false;
  1434. }
  1435. void wxPGProperty::SetAttribute( const wxString& name, wxVariant value )
  1436. {
  1437. if ( DoSetAttribute( name, value ) )
  1438. {
  1439. // Support working without grid, when possible
  1440. if ( wxPGGlobalVars->HasExtraStyle( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES ) )
  1441. return;
  1442. }
  1443. m_attributes.Set( name, value );
  1444. }
  1445. void wxPGProperty::SetAttributes( const wxPGAttributeStorage& attributes )
  1446. {
  1447. wxPGAttributeStorage::const_iterator it = attributes.StartIteration();
  1448. wxVariant variant;
  1449. while ( attributes.GetNext(it, variant) )
  1450. SetAttribute( variant.GetName(), variant );
  1451. }
  1452. wxVariant wxPGProperty::DoGetAttribute( const wxString& WXUNUSED(name) ) const
  1453. {
  1454. return wxVariant();
  1455. }
  1456. wxVariant wxPGProperty::GetAttribute( const wxString& name ) const
  1457. {
  1458. return m_attributes.FindValue(name);
  1459. }
  1460. wxString wxPGProperty::GetAttribute( const wxString& name, const wxString& defVal ) const
  1461. {
  1462. wxVariant variant = m_attributes.FindValue(name);
  1463. if ( !variant.IsNull() )
  1464. return variant.GetString();
  1465. return defVal;
  1466. }
  1467. long wxPGProperty::GetAttributeAsLong( const wxString& name, long defVal ) const
  1468. {
  1469. wxVariant variant = m_attributes.FindValue(name);
  1470. if ( variant.IsNull() )
  1471. return defVal;
  1472. return variant.GetLong();
  1473. }
  1474. double wxPGProperty::GetAttributeAsDouble( const wxString& name, double defVal ) const
  1475. {
  1476. wxVariant variant = m_attributes.FindValue(name);
  1477. if ( variant.IsNull() )
  1478. return defVal;
  1479. return variant.GetDouble();
  1480. }
  1481. wxVariant wxPGProperty::GetAttributesAsList() const
  1482. {
  1483. wxVariantList tempList;
  1484. wxVariant v( tempList, wxString::Format(wxS("@%s@attr"),m_name.c_str()) );
  1485. wxPGAttributeStorage::const_iterator it = m_attributes.StartIteration();
  1486. wxVariant variant;
  1487. while ( m_attributes.GetNext(it, variant) )
  1488. v.Append(variant);
  1489. return v;
  1490. }
  1491. // Slots of utility flags are NULL
  1492. const unsigned int gs_propFlagToStringSize = 14;
  1493. static const wxChar* const gs_propFlagToString[gs_propFlagToStringSize] = {
  1494. NULL,
  1495. wxT("DISABLED"),
  1496. wxT("HIDDEN"),
  1497. NULL,
  1498. wxT("NOEDITOR"),
  1499. wxT("COLLAPSED"),
  1500. NULL,
  1501. NULL,
  1502. NULL,
  1503. NULL,
  1504. NULL,
  1505. NULL,
  1506. NULL,
  1507. NULL
  1508. };
  1509. wxString wxPGProperty::GetFlagsAsString( FlagType flagsMask ) const
  1510. {
  1511. wxString s;
  1512. int relevantFlags = m_flags & flagsMask & wxPG_STRING_STORED_FLAGS;
  1513. FlagType a = 1;
  1514. unsigned int i = 0;
  1515. for ( i=0; i<gs_propFlagToStringSize; i++ )
  1516. {
  1517. if ( relevantFlags & a )
  1518. {
  1519. const wxChar* fs = gs_propFlagToString[i];
  1520. wxASSERT(fs);
  1521. if ( !s.empty() )
  1522. s << wxS("|");
  1523. s << fs;
  1524. }
  1525. a = a << 1;
  1526. }
  1527. return s;
  1528. }
  1529. void wxPGProperty::SetFlagsFromString( const wxString& str )
  1530. {
  1531. FlagType flags = 0;
  1532. WX_PG_TOKENIZER1_BEGIN(str, wxS('|'))
  1533. unsigned int i;
  1534. for ( i=0; i<gs_propFlagToStringSize; i++ )
  1535. {
  1536. const wxChar* fs = gs_propFlagToString[i];
  1537. if ( fs && str == fs )
  1538. {
  1539. flags |= (1<<i);
  1540. break;
  1541. }
  1542. }
  1543. WX_PG_TOKENIZER1_END()
  1544. m_flags = (m_flags & ~wxPG_STRING_STORED_FLAGS) | flags;
  1545. }
  1546. wxValidator* wxPGProperty::DoGetValidator() const
  1547. {
  1548. return NULL;
  1549. }
  1550. int wxPGProperty::InsertChoice( const wxString& label, int index, int value )
  1551. {
  1552. wxPropertyGrid* pg = GetGrid();
  1553. int sel = GetChoiceSelection();
  1554. int newSel = sel;
  1555. if ( index == wxNOT_FOUND )
  1556. index = m_choices.GetCount();
  1557. if ( index <= sel )
  1558. newSel++;
  1559. m_choices.Insert(label, index, value);
  1560. if ( sel != newSel )
  1561. SetChoiceSelection(newSel);
  1562. if ( this == pg->GetSelection() )
  1563. GetEditorClass()->InsertItem(pg->GetEditorControl(),label,index);
  1564. return index;
  1565. }
  1566. void wxPGProperty::DeleteChoice( int index )
  1567. {
  1568. wxPropertyGrid* pg = GetGrid();
  1569. int sel = GetChoiceSelection();
  1570. int newSel = sel;
  1571. // Adjust current value
  1572. if ( sel == index )
  1573. {
  1574. SetValueToUnspecified();
  1575. newSel = 0;
  1576. }
  1577. else if ( index < sel )
  1578. {
  1579. newSel--;
  1580. }
  1581. m_choices.RemoveAt(index);
  1582. if ( sel != newSel )
  1583. SetChoiceSelection(newSel);
  1584. if ( this == pg->GetSelection() )
  1585. GetEditorClass()->DeleteItem(pg->GetEditorControl(), index);
  1586. }
  1587. int wxPGProperty::GetChoiceSelection() const
  1588. {
  1589. wxVariant value = GetValue();
  1590. wxString valueType = value.GetType();
  1591. int index = wxNOT_FOUND;
  1592. if ( IsValueUnspecified() || !m_choices.GetCount() )
  1593. return wxNOT_FOUND;
  1594. if ( valueType == wxPG_VARIANT_TYPE_LONG )
  1595. {
  1596. index = value.GetLong();
  1597. }
  1598. else if ( valueType == wxPG_VARIANT_TYPE_STRING )
  1599. {
  1600. index = m_choices.Index(value.GetString());
  1601. }
  1602. else if ( valueType == wxPG_VARIANT_TYPE_BOOL )
  1603. {
  1604. index = value.GetBool()? 1 : 0;
  1605. }
  1606. return index;
  1607. }
  1608. void wxPGProperty::SetChoiceSelection( int newValue )
  1609. {
  1610. // Changes value of a property with choices, but only
  1611. // works if the value type is long or string.
  1612. wxString valueType = GetValue().GetType();
  1613. wxCHECK_RET( m_choices.IsOk(), wxT("invalid choiceinfo") );
  1614. if ( valueType == wxPG_VARIANT_TYPE_STRING )
  1615. {
  1616. SetValue( m_choices.GetLabel(newValue) );
  1617. }
  1618. else // if ( valueType == wxPG_VARIANT_TYPE_LONG )
  1619. {
  1620. SetValue( (long) newValue );
  1621. }
  1622. }
  1623. bool wxPGProperty::SetChoices( const wxPGChoices& choices )
  1624. {
  1625. // Property must be de-selected first (otherwise choices in
  1626. // the control would be de-synced with true choices)
  1627. wxPropertyGrid* pg = GetGrid();
  1628. if ( pg && pg->GetSelection() == this )
  1629. pg->ClearSelection();
  1630. m_choices.Assign(choices);
  1631. {
  1632. // This may be needed to trigger some initialization
  1633. // (but don't do it if property is somewhat uninitialized)
  1634. wxVariant defVal = GetDefaultValue();
  1635. if ( defVal.IsNull() )
  1636. return false;
  1637. SetValue(defVal);
  1638. }
  1639. return true;
  1640. }
  1641. const wxPGEditor* wxPGProperty::GetEditorClass() const
  1642. {
  1643. const wxPGEditor* editor;
  1644. if ( !m_customEditor )
  1645. {
  1646. editor = DoGetEditorClass();
  1647. }
  1648. else
  1649. editor = m_customEditor;
  1650. //
  1651. // Maybe override editor if common value specified
  1652. if ( GetDisplayedCommonValueCount() )
  1653. {
  1654. // TextCtrlAndButton -> ComboBoxAndButton
  1655. if ( wxDynamicCast(editor, wxPGTextCtrlAndButtonEditor) )
  1656. editor = wxPGEditor_ChoiceAndButton;
  1657. // TextCtrl -> ComboBox
  1658. else if ( wxDynamicCast(editor, wxPGTextCtrlEditor) )
  1659. editor = wxPGEditor_ComboBox;
  1660. }
  1661. return editor;
  1662. }
  1663. bool wxPGProperty::Hide( bool hide, int flags )
  1664. {
  1665. wxPropertyGrid* pg = GetGrid();
  1666. if ( pg )
  1667. return pg->HideProperty(this, hide, flags);
  1668. return DoHide( hide, flags );
  1669. }
  1670. bool wxPGProperty::DoHide( bool hide, int flags )
  1671. {
  1672. if ( !hide )
  1673. ClearFlag( wxPG_PROP_HIDDEN );
  1674. else
  1675. SetFlag( wxPG_PROP_HIDDEN );
  1676. if ( flags & wxPG_RECURSE )
  1677. {
  1678. unsigned int i;
  1679. for ( i = 0; i < GetChildCount(); i++ )
  1680. Item(i)->DoHide(hide, flags | wxPG_RECURSE_STARTS);
  1681. }
  1682. return true;
  1683. }
  1684. bool wxPGProperty::HasVisibleChildren() const
  1685. {
  1686. unsigned int i;
  1687. for ( i=0; i<GetChildCount(); i++ )
  1688. {
  1689. wxPGProperty* child = Item(i);
  1690. if ( !child->HasFlag(wxPG_PROP_HIDDEN) )
  1691. return true;
  1692. }
  1693. return false;
  1694. }
  1695. bool wxPGProperty::RecreateEditor()
  1696. {
  1697. wxPropertyGrid* pg = GetGrid();
  1698. wxASSERT(pg);
  1699. wxPGProperty* selected = pg->GetSelection();
  1700. if ( this == selected )
  1701. {
  1702. pg->DoSelectProperty(this, wxPG_SEL_FORCE);
  1703. return true;
  1704. }
  1705. return false;
  1706. }
  1707. void wxPGProperty::SetValueImage( wxBitmap& bmp )
  1708. {
  1709. delete m_valueBitmap;
  1710. if ( &bmp && bmp.IsOk() )
  1711. {
  1712. // Resize the image
  1713. wxSize maxSz = GetGrid()->GetImageSize();
  1714. wxSize imSz(bmp.GetWidth(),bmp.GetHeight());
  1715. if ( imSz.y != maxSz.y )
  1716. {
  1717. #if wxUSE_IMAGE
  1718. // Here we use high-quality wxImage scaling functions available
  1719. wxImage img = bmp.ConvertToImage();
  1720. double scaleY = (double)maxSz.y / (double)imSz.y;
  1721. img.Rescale(wxRound(bmp.GetWidth()*scaleY),
  1722. wxRound(bmp.GetHeight()*scaleY),
  1723. wxIMAGE_QUALITY_HIGH);
  1724. wxBitmap* bmpNew = new wxBitmap(img, 32);
  1725. #else
  1726. // This is the old, deprecated method of scaling the image
  1727. wxBitmap* bmpNew = new wxBitmap(maxSz.x,maxSz.y,bmp.GetDepth());
  1728. wxMemoryDC dc;
  1729. dc.SelectObject(*bmpNew);
  1730. double scaleY = (double)maxSz.y / (double)imSz.y;
  1731. dc.SetUserScale(scaleY, scaleY);
  1732. dc.DrawBitmap(bmp, 0, 0);
  1733. #endif
  1734. m_valueBitmap = bmpNew;
  1735. }
  1736. else
  1737. {
  1738. m_valueBitmap = new wxBitmap(bmp);
  1739. }
  1740. m_flags |= wxPG_PROP_CUSTOMIMAGE;
  1741. }
  1742. else
  1743. {
  1744. m_valueBitmap = NULL;
  1745. m_flags &= ~(wxPG_PROP_CUSTOMIMAGE);
  1746. }
  1747. }
  1748. wxPGProperty* wxPGProperty::GetMainParent() const
  1749. {
  1750. const wxPGProperty* curChild = this;
  1751. const wxPGProperty* curParent = m_parent;
  1752. while ( curParent && !curParent->IsCategory() )
  1753. {
  1754. curChild = curParent;
  1755. curParent = curParent->m_parent;
  1756. }
  1757. return (wxPGProperty*) curChild;
  1758. }
  1759. const wxPGProperty* wxPGProperty::GetLastVisibleSubItem() const
  1760. {
  1761. //
  1762. // Returns last visible sub-item, recursively.
  1763. if ( !IsExpanded() || !GetChildCount() )
  1764. return this;
  1765. return Last()->GetLastVisibleSubItem();
  1766. }
  1767. bool wxPGProperty::IsVisible() const
  1768. {
  1769. const wxPGProperty* parent;
  1770. if ( HasFlag(wxPG_PROP_HIDDEN) )
  1771. return false;
  1772. for ( parent = GetParent(); parent != NULL; parent = parent->GetParent() )
  1773. {
  1774. if ( !parent->IsExpanded() || parent->HasFlag(wxPG_PROP_HIDDEN) )
  1775. return false;
  1776. }
  1777. return true;
  1778. }
  1779. wxPropertyGrid* wxPGProperty::GetGridIfDisplayed() const
  1780. {
  1781. wxPropertyGridPageState* state = GetParentState();
  1782. if ( !state )
  1783. return NULL;
  1784. wxPropertyGrid* propGrid = state->GetGrid();
  1785. if ( state == propGrid->GetState() )
  1786. return propGrid;
  1787. return NULL;
  1788. }
  1789. int wxPGProperty::GetY2( int lh ) const
  1790. {
  1791. const wxPGProperty* parent;
  1792. const wxPGProperty* child = this;
  1793. int y = 0;
  1794. for ( parent = GetParent(); parent != NULL; parent = child->GetParent() )
  1795. {
  1796. if ( !parent->IsExpanded() )
  1797. return parent->GetY2(lh);
  1798. y += parent->GetChildrenHeight(lh, child->GetIndexInParent());
  1799. y += lh;
  1800. child = parent;
  1801. }
  1802. y -= lh; // need to reduce one level
  1803. return y;
  1804. }
  1805. int wxPGProperty::GetY() const
  1806. {
  1807. return GetY2(GetGrid()->GetRowHeight());
  1808. }
  1809. // This is used by Insert etc.
  1810. void wxPGProperty::DoAddChild( wxPGProperty* prop, int index,
  1811. bool correct_mode )
  1812. {
  1813. if ( index < 0 || (size_t)index >= m_children.size() )
  1814. {
  1815. if ( correct_mode ) prop->m_arrIndex = m_children.size();
  1816. m_children.push_back( prop );
  1817. }
  1818. else
  1819. {
  1820. m_children.insert( m_children.begin()+index, prop);
  1821. if ( correct_mode ) FixIndicesOfChildren( index );
  1822. }
  1823. prop->m_parent = this;
  1824. }
  1825. void wxPGProperty::DoPreAddChild( int index, wxPGProperty* prop )
  1826. {
  1827. wxASSERT_MSG( prop->GetBaseName().length(),
  1828. "Property's children must have unique, non-empty "
  1829. "names within their scope" );
  1830. prop->m_arrIndex = index;
  1831. m_children.insert( m_children.begin()+index,
  1832. prop );
  1833. int custImgHeight = prop->OnMeasureImage().y;
  1834. if ( custImgHeight < 0 /*|| custImgHeight > 1*/ )
  1835. prop->m_flags |= wxPG_PROP_CUSTOMIMAGE;
  1836. prop->m_parent = this;
  1837. }
  1838. void wxPGProperty::AddPrivateChild( wxPGProperty* prop )
  1839. {
  1840. if ( !(m_flags & wxPG_PROP_PARENTAL_FLAGS) )
  1841. SetParentalType(wxPG_PROP_AGGREGATE);
  1842. wxASSERT_MSG( (m_flags & wxPG_PROP_PARENTAL_FLAGS) ==
  1843. wxPG_PROP_AGGREGATE,
  1844. "Do not mix up AddPrivateChild() calls with other "
  1845. "property adders." );
  1846. DoPreAddChild( m_children.size(), prop );
  1847. }
  1848. #if wxPG_COMPATIBILITY_1_4
  1849. void wxPGProperty::AddChild( wxPGProperty* prop )
  1850. {
  1851. AddPrivateChild(prop);
  1852. }
  1853. #endif
  1854. wxPGProperty* wxPGProperty::InsertChild( int index,
  1855. wxPGProperty* childProperty )
  1856. {
  1857. if ( index < 0 )
  1858. index = m_children.size();
  1859. if ( m_parentState )
  1860. {
  1861. m_parentState->DoInsert(this, index, childProperty);
  1862. }
  1863. else
  1864. {
  1865. if ( !(m_flags & wxPG_PROP_PARENTAL_FLAGS) )
  1866. SetParentalType(wxPG_PROP_MISC_PARENT);
  1867. wxASSERT_MSG( (m_flags & wxPG_PROP_PARENTAL_FLAGS) ==
  1868. wxPG_PROP_MISC_PARENT,
  1869. "Do not mix up AddPrivateChild() calls with other "
  1870. "property adders." );
  1871. DoPreAddChild( index, childProperty );
  1872. }
  1873. return childProperty;
  1874. }
  1875. void wxPGProperty::RemoveChild( wxPGProperty* p )
  1876. {
  1877. wxArrayPGProperty::iterator it;
  1878. wxArrayPGProperty& children = m_children;
  1879. for ( it=children.begin(); it != children.end(); it++ )
  1880. {
  1881. if ( *it == p )
  1882. {
  1883. children.erase(it);
  1884. break;
  1885. }
  1886. }
  1887. }
  1888. void wxPGProperty::AdaptListToValue( wxVariant& list, wxVariant* value ) const
  1889. {
  1890. wxASSERT( GetChildCount() );
  1891. wxASSERT( !IsCategory() );
  1892. *value = GetValue();
  1893. if ( !list.GetCount() )
  1894. return;
  1895. wxASSERT( GetChildCount() >= (unsigned int)list.GetCount() );
  1896. bool allChildrenSpecified;
  1897. // Don't fully update aggregate properties unless all children have
  1898. // specified value
  1899. if ( HasFlag(wxPG_PROP_AGGREGATE) )
  1900. allChildrenSpecified = AreAllChildrenSpecified(&list);
  1901. else
  1902. allChildrenSpecified = true;
  1903. unsigned int i;
  1904. unsigned int n = 0;
  1905. wxVariant childValue = list[n];
  1906. //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetBaseName().c_str());
  1907. for ( i=0; i<GetChildCount(); i++ )
  1908. {
  1909. const wxPGProperty* child = Item(i);
  1910. if ( childValue.GetName() == child->GetBaseName() )
  1911. {
  1912. //wxLogDebug(wxT(" %s(n=%i), %s"),childValue.GetName().c_str(),n,childValue.GetType().c_str());
  1913. if ( childValue.GetType() == wxPG_VARIANT_TYPE_LIST )
  1914. {
  1915. wxVariant cv2(child->GetValue());
  1916. child->AdaptListToValue(childValue, &cv2);
  1917. childValue = cv2;
  1918. }
  1919. if ( allChildrenSpecified )
  1920. {
  1921. *value = ChildChanged(*value, i, childValue);
  1922. }
  1923. n++;
  1924. if ( n == (unsigned int)list.GetCount() )
  1925. break;
  1926. childValue = list[n];
  1927. }
  1928. }
  1929. }
  1930. void wxPGProperty::FixIndicesOfChildren( unsigned int starthere )
  1931. {
  1932. size_t i;
  1933. for ( i=starthere;i<GetChildCount();i++)
  1934. Item(i)->m_arrIndex = i;
  1935. }
  1936. // Returns (direct) child property with given name (or NULL if not found)
  1937. wxPGProperty* wxPGProperty::GetPropertyByName( const wxString& name ) const
  1938. {
  1939. size_t i;
  1940. for ( i=0; i<GetChildCount(); i++ )
  1941. {
  1942. wxPGProperty* p = Item(i);
  1943. if ( p->m_name == name )
  1944. return p;
  1945. }
  1946. // Does it have point, then?
  1947. int pos = name.Find(wxS('.'));
  1948. if ( pos <= 0 )
  1949. return NULL;
  1950. wxPGProperty* p = GetPropertyByName(name. substr(0,pos));
  1951. if ( !p || !p->GetChildCount() )
  1952. return NULL;
  1953. return p->GetPropertyByName(name.substr(pos+1,name.length()-pos-1));
  1954. }
  1955. wxPGProperty* wxPGProperty::GetPropertyByNameWH( const wxString& name, unsigned int hintIndex ) const
  1956. {
  1957. unsigned int i = hintIndex;
  1958. if ( i >= GetChildCount() )
  1959. i = 0;
  1960. unsigned int lastIndex = i - 1;
  1961. if ( lastIndex >= GetChildCount() )
  1962. lastIndex = GetChildCount() - 1;
  1963. for (;;)
  1964. {
  1965. wxPGProperty* p = Item(i);
  1966. if ( p->m_name == name )
  1967. return p;
  1968. if ( i == lastIndex )
  1969. break;
  1970. i++;
  1971. if ( i == GetChildCount() )
  1972. i = 0;
  1973. };
  1974. return NULL;
  1975. }
  1976. int wxPGProperty::GetChildrenHeight( int lh, int iMax_ ) const
  1977. {
  1978. // Returns height of children, recursively, and
  1979. // by taking expanded/collapsed status into account.
  1980. //
  1981. // iMax is used when finding property y-positions.
  1982. //
  1983. unsigned int i = 0;
  1984. int h = 0;
  1985. if ( iMax_ == -1 )
  1986. iMax_ = GetChildCount();
  1987. unsigned int iMax = iMax_;
  1988. wxASSERT( iMax <= GetChildCount() );
  1989. if ( !IsExpanded() && GetParent() )
  1990. return 0;
  1991. while ( i < iMax )
  1992. {
  1993. wxPGProperty* pwc = (wxPGProperty*) Item(i);
  1994. if ( !pwc->HasFlag(wxPG_PROP_HIDDEN) )
  1995. {
  1996. if ( !pwc->IsExpanded() ||
  1997. pwc->GetChildCount() == 0 )
  1998. h += lh;
  1999. else
  2000. h += pwc->GetChildrenHeight(lh) + lh;
  2001. }
  2002. i++;
  2003. }
  2004. return h;
  2005. }
  2006. wxPGProperty* wxPGProperty::GetItemAtY( unsigned int y,
  2007. unsigned int lh,
  2008. unsigned int* nextItemY ) const
  2009. {
  2010. wxASSERT( nextItemY );
  2011. // Linear search at the moment
  2012. //
  2013. // nextItemY = y of next visible property, final value will be written back.
  2014. wxPGProperty* result = NULL;
  2015. wxPGProperty* current = NULL;
  2016. unsigned int iy = *nextItemY;
  2017. unsigned int i = 0;
  2018. unsigned int iMax = GetChildCount();
  2019. while ( i < iMax )
  2020. {
  2021. wxPGProperty* pwc = Item(i);
  2022. if ( !pwc->HasFlag(wxPG_PROP_HIDDEN) )
  2023. {
  2024. // Found?
  2025. if ( y < iy )
  2026. {
  2027. result = current;
  2028. break;
  2029. }
  2030. iy += lh;
  2031. if ( pwc->IsExpanded() &&
  2032. pwc->GetChildCount() > 0 )
  2033. {
  2034. result = (wxPGProperty*) pwc->GetItemAtY( y, lh, &iy );
  2035. if ( result )
  2036. break;
  2037. }
  2038. current = pwc;
  2039. }
  2040. i++;
  2041. }
  2042. // Found?
  2043. if ( !result && y < iy )
  2044. result = current;
  2045. *nextItemY = iy;
  2046. /*
  2047. if ( current )
  2048. {
  2049. wxLogDebug(wxT("%s::GetItemAtY(%i) -> %s"),this->GetLabel().c_str(),y,current->GetLabel().c_str());
  2050. }
  2051. else
  2052. {
  2053. wxLogDebug(wxT("%s::GetItemAtY(%i) -> NULL"),this->GetLabel().c_str(),y);
  2054. }
  2055. */
  2056. return (wxPGProperty*) result;
  2057. }
  2058. void wxPGProperty::Empty()
  2059. {
  2060. size_t i;
  2061. if ( !HasFlag(wxPG_PROP_CHILDREN_ARE_COPIES) )
  2062. {
  2063. for ( i=0; i<GetChildCount(); i++ )
  2064. {
  2065. delete m_children[i];
  2066. }
  2067. }
  2068. m_children.clear();
  2069. }
  2070. wxPGProperty* wxPGProperty::GetItemAtY( unsigned int y ) const
  2071. {
  2072. unsigned int nextItem;
  2073. return GetItemAtY( y, GetGrid()->GetRowHeight(), &nextItem);
  2074. }
  2075. void wxPGProperty::DeleteChildren()
  2076. {
  2077. wxPropertyGridPageState* state = m_parentState;
  2078. if ( !GetChildCount() )
  2079. return;
  2080. // Because deletion is sometimes deferred, we have to use
  2081. // this sort of code for enumerating the child properties.
  2082. unsigned int i = GetChildCount();
  2083. while ( i > 0 )
  2084. {
  2085. i--;
  2086. state->DoDelete(Item(i), true);
  2087. }
  2088. }
  2089. bool wxPGProperty::IsChildSelected( bool recursive ) const
  2090. {
  2091. size_t i;
  2092. for ( i = 0; i < GetChildCount(); i++ )
  2093. {
  2094. wxPGProperty* child = Item(i);
  2095. // Test child
  2096. if ( m_parentState->DoIsPropertySelected( child ) )
  2097. return true;
  2098. // Test sub-childs
  2099. if ( recursive && child->IsChildSelected( recursive ) )
  2100. return true;
  2101. }
  2102. return false;
  2103. }
  2104. wxVariant wxPGProperty::ChildChanged( wxVariant& WXUNUSED(thisValue),
  2105. int WXUNUSED(childIndex),
  2106. wxVariant& WXUNUSED(childValue) ) const
  2107. {
  2108. return wxNullVariant;
  2109. }
  2110. bool wxPGProperty::AreAllChildrenSpecified( wxVariant* pendingList ) const
  2111. {
  2112. unsigned int i;
  2113. const wxVariantList* pList = NULL;
  2114. wxVariantList::const_iterator node;
  2115. if ( pendingList )
  2116. {
  2117. pList = &pendingList->GetList();
  2118. node = pList->begin();
  2119. }
  2120. for ( i=0; i<GetChildCount(); i++ )
  2121. {
  2122. wxPGProperty* child = Item(i);
  2123. const wxVariant* listValue = NULL;
  2124. wxVariant value;
  2125. if ( pendingList )
  2126. {
  2127. const wxString& childName = child->GetBaseName();
  2128. for ( ; node != pList->end(); ++node )
  2129. {
  2130. const wxVariant& item = *((const wxVariant*)*node);
  2131. if ( item.GetName() == childName )
  2132. {
  2133. listValue = &item;
  2134. value = item;
  2135. break;
  2136. }
  2137. }
  2138. }
  2139. if ( !listValue )
  2140. value = child->GetValue();
  2141. if ( value.IsNull() )
  2142. return false;
  2143. // Check recursively
  2144. if ( child->GetChildCount() )
  2145. {
  2146. const wxVariant* childList = NULL;
  2147. if ( listValue && listValue->GetType() == wxPG_VARIANT_TYPE_LIST )
  2148. childList = listValue;
  2149. if ( !child->AreAllChildrenSpecified((wxVariant*)childList) )
  2150. return false;
  2151. }
  2152. }
  2153. return true;
  2154. }
  2155. wxPGProperty* wxPGProperty::UpdateParentValues()
  2156. {
  2157. wxPGProperty* parent = m_parent;
  2158. if ( parent && parent->HasFlag(wxPG_PROP_COMPOSED_VALUE) &&
  2159. !parent->IsCategory() && !parent->IsRoot() )
  2160. {
  2161. wxString s;
  2162. parent->DoGenerateComposedValue(s);
  2163. parent->m_value = s;
  2164. return parent->UpdateParentValues();
  2165. }
  2166. return this;
  2167. }
  2168. bool wxPGProperty::IsTextEditable() const
  2169. {
  2170. if ( HasFlag(wxPG_PROP_READONLY) )
  2171. return false;
  2172. if ( HasFlag(wxPG_PROP_NOEDITOR) &&
  2173. (GetChildCount() ||
  2174. wxString(GetEditorClass()->GetClassInfo()->GetClassName()).EndsWith(wxS("Button")))
  2175. )
  2176. return false;
  2177. return true;
  2178. }
  2179. // Call after fixed sub-properties added/removed after creation.
  2180. // if oldSelInd >= 0 and < new max items, then selection is
  2181. // moved to it. Note: oldSelInd -2 indicates that this property
  2182. // should be selected.
  2183. void wxPGProperty::SubPropsChanged( int oldSelInd )
  2184. {
  2185. wxPropertyGridPageState* state = GetParentState();
  2186. wxPropertyGrid* grid = state->GetGrid();
  2187. //
  2188. // Re-repare children (recursively)
  2189. for ( unsigned int i=0; i<GetChildCount(); i++ )
  2190. {
  2191. wxPGProperty* child = Item(i);
  2192. child->InitAfterAdded(state, grid);
  2193. }
  2194. wxPGProperty* sel = NULL;
  2195. if ( oldSelInd >= (int)m_children.size() )
  2196. oldSelInd = (int)m_children.size() - 1;
  2197. if ( oldSelInd >= 0 )
  2198. sel = m_children[oldSelInd];
  2199. else if ( oldSelInd == -2 )
  2200. sel = this;
  2201. if ( sel )
  2202. state->DoSelectProperty(sel);
  2203. if ( state == grid->GetState() )
  2204. {
  2205. grid->GetPanel()->Refresh();
  2206. }
  2207. }
  2208. // -----------------------------------------------------------------------
  2209. // wxPGRootProperty
  2210. // -----------------------------------------------------------------------
  2211. WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty,none,TextCtrl)
  2212. IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty, wxPGProperty)
  2213. wxPGRootProperty::wxPGRootProperty( const wxString& name )
  2214. : wxPGProperty()
  2215. {
  2216. m_name = name;
  2217. m_label = m_name;
  2218. SetParentalType(0);
  2219. m_depth = 0;
  2220. }
  2221. wxPGRootProperty::~wxPGRootProperty()
  2222. {
  2223. }
  2224. // -----------------------------------------------------------------------
  2225. // wxPropertyCategory
  2226. // -----------------------------------------------------------------------
  2227. WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory,none,TextCtrl)
  2228. IMPLEMENT_DYNAMIC_CLASS(wxPropertyCategory, wxPGProperty)
  2229. void wxPropertyCategory::Init()
  2230. {
  2231. // don't set colour - prepareadditem method should do this
  2232. SetParentalType(wxPG_PROP_CATEGORY);
  2233. m_capFgColIndex = 1;
  2234. m_textExtent = -1;
  2235. }
  2236. wxPropertyCategory::wxPropertyCategory()
  2237. : wxPGProperty()
  2238. {
  2239. Init();
  2240. }
  2241. wxPropertyCategory::wxPropertyCategory( const wxString &label, const wxString& name )
  2242. : wxPGProperty(label,name)
  2243. {
  2244. Init();
  2245. }
  2246. wxPropertyCategory::~wxPropertyCategory()
  2247. {
  2248. }
  2249. wxString wxPropertyCategory::ValueToString( wxVariant& WXUNUSED(value),
  2250. int WXUNUSED(argFlags) ) const
  2251. {
  2252. if ( m_value.GetType() == wxPG_VARIANT_TYPE_STRING )
  2253. return m_value.GetString();
  2254. return wxEmptyString;
  2255. }
  2256. wxString wxPropertyCategory::GetValueAsString( int argFlags ) const
  2257. {
  2258. #if wxPG_COMPATIBILITY_1_4
  2259. // This is backwards compatibility test
  2260. // That is, to make sure this function is not overridden
  2261. // (instead, ValueToString() should be).
  2262. if ( argFlags == 0xFFFF )
  2263. {
  2264. // Do not override! (for backwards compliancy)
  2265. return g_invalidStringContent;
  2266. }
  2267. #endif
  2268. // Unspecified value is always empty string
  2269. if ( IsValueUnspecified() )
  2270. return wxEmptyString;
  2271. return wxPGProperty::GetValueAsString(argFlags);
  2272. }
  2273. int wxPropertyCategory::GetTextExtent( const wxWindow* wnd, const wxFont& font ) const
  2274. {
  2275. if ( m_textExtent > 0 )
  2276. return m_textExtent;
  2277. int x = 0, y = 0;
  2278. ((wxWindow*)wnd)->GetTextExtent( m_label, &x, &y, 0, 0, &font );
  2279. return x;
  2280. }
  2281. void wxPropertyCategory::CalculateTextExtent( wxWindow* wnd, const wxFont& font )
  2282. {
  2283. int x = 0, y = 0;
  2284. wnd->GetTextExtent( m_label, &x, &y, 0, 0, &font );
  2285. m_textExtent = x;
  2286. }
  2287. // -----------------------------------------------------------------------
  2288. // wxPGChoices
  2289. // -----------------------------------------------------------------------
  2290. wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, int value )
  2291. {
  2292. AllocExclusive();
  2293. wxPGChoiceEntry entry(label, value);
  2294. return m_data->Insert( -1, entry );
  2295. }
  2296. // -----------------------------------------------------------------------
  2297. wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, const wxBitmap& bitmap, int value )
  2298. {
  2299. AllocExclusive();
  2300. wxPGChoiceEntry entry(label, value);
  2301. entry.SetBitmap(bitmap);
  2302. return m_data->Insert( -1, entry );
  2303. }
  2304. // -----------------------------------------------------------------------
  2305. wxPGChoiceEntry& wxPGChoices::Insert( const wxPGChoiceEntry& entry, int index )
  2306. {
  2307. AllocExclusive();
  2308. return m_data->Insert( index, entry );
  2309. }
  2310. // -----------------------------------------------------------------------
  2311. wxPGChoiceEntry& wxPGChoices::Insert( const wxString& label, int index, int value )
  2312. {
  2313. AllocExclusive();
  2314. wxPGChoiceEntry entry(label, value);
  2315. return m_data->Insert( index, entry );
  2316. }
  2317. // -----------------------------------------------------------------------
  2318. wxPGChoiceEntry& wxPGChoices::AddAsSorted( const wxString& label, int value )
  2319. {
  2320. AllocExclusive();
  2321. size_t index = 0;
  2322. while ( index < GetCount() )
  2323. {
  2324. int cmpRes = GetLabel(index).Cmp(label);
  2325. if ( cmpRes > 0 )
  2326. break;
  2327. index++;
  2328. }
  2329. wxPGChoiceEntry entry(label, value);
  2330. return m_data->Insert( index, entry );
  2331. }
  2332. // -----------------------------------------------------------------------
  2333. void wxPGChoices::Add( const wxChar* const* labels, const ValArrItem* values )
  2334. {
  2335. AllocExclusive();
  2336. unsigned int itemcount = 0;
  2337. const wxChar* const* p = &labels[0];
  2338. while ( *p ) { p++; itemcount++; }
  2339. unsigned int i;
  2340. for ( i = 0; i < itemcount; i++ )
  2341. {
  2342. int value = i;
  2343. if ( values )
  2344. value = values[i];
  2345. wxPGChoiceEntry entry(labels[i], value);
  2346. m_data->Insert( i, entry );
  2347. }
  2348. }
  2349. // -----------------------------------------------------------------------
  2350. void wxPGChoices::Add( const wxArrayString& arr, const wxArrayInt& arrint )
  2351. {
  2352. AllocExclusive();
  2353. unsigned int i;
  2354. unsigned int itemcount = arr.size();
  2355. for ( i = 0; i < itemcount; i++ )
  2356. {
  2357. int value = i;
  2358. if ( &arrint && arrint.size() )
  2359. value = arrint[i];
  2360. wxPGChoiceEntry entry(arr[i], value);
  2361. m_data->Insert( i, entry );
  2362. }
  2363. }
  2364. // -----------------------------------------------------------------------
  2365. void wxPGChoices::RemoveAt(size_t nIndex, size_t count)
  2366. {
  2367. AllocExclusive();
  2368. wxASSERT( m_data->GetRefCount() != -1 );
  2369. m_data->m_items.erase(m_data->m_items.begin()+nIndex,
  2370. m_data->m_items.begin()+nIndex+count);
  2371. }
  2372. // -----------------------------------------------------------------------
  2373. void wxPGChoices::Clear()
  2374. {
  2375. if ( m_data != wxPGChoicesEmptyData )
  2376. {
  2377. AllocExclusive();
  2378. m_data->Clear();
  2379. }
  2380. }
  2381. // -----------------------------------------------------------------------
  2382. int wxPGChoices::Index( const wxString& str ) const
  2383. {
  2384. if ( IsOk() )
  2385. {
  2386. unsigned int i;
  2387. for ( i=0; i< m_data->GetCount(); i++ )
  2388. {
  2389. const wxPGChoiceEntry& entry = m_data->Item(i);
  2390. if ( entry.HasText() && entry.GetText() == str )
  2391. return i;
  2392. }
  2393. }
  2394. return -1;
  2395. }
  2396. // -----------------------------------------------------------------------
  2397. int wxPGChoices::Index( int val ) const
  2398. {
  2399. if ( IsOk() )
  2400. {
  2401. unsigned int i;
  2402. for ( i=0; i< m_data->GetCount(); i++ )
  2403. {
  2404. const wxPGChoiceEntry& entry = m_data->Item(i);
  2405. if ( entry.GetValue() == val )
  2406. return i;
  2407. }
  2408. }
  2409. return -1;
  2410. }
  2411. // -----------------------------------------------------------------------
  2412. wxArrayString wxPGChoices::GetLabels() const
  2413. {
  2414. wxArrayString arr;
  2415. unsigned int i;
  2416. if ( this && IsOk() )
  2417. for ( i=0; i<GetCount(); i++ )
  2418. arr.push_back(GetLabel(i));
  2419. return arr;
  2420. }
  2421. // -----------------------------------------------------------------------
  2422. wxArrayInt wxPGChoices::GetValuesForStrings( const wxArrayString& strings ) const
  2423. {
  2424. wxArrayInt arr;
  2425. if ( IsOk() )
  2426. {
  2427. unsigned int i;
  2428. for ( i=0; i< strings.size(); i++ )
  2429. {
  2430. int index = Index(strings[i]);
  2431. if ( index >= 0 )
  2432. arr.Add(GetValue(index));
  2433. else
  2434. arr.Add(wxPG_INVALID_VALUE);
  2435. }
  2436. }
  2437. return arr;
  2438. }
  2439. // -----------------------------------------------------------------------
  2440. wxArrayInt wxPGChoices::GetIndicesForStrings( const wxArrayString& strings,
  2441. wxArrayString* unmatched ) const
  2442. {
  2443. wxArrayInt arr;
  2444. if ( IsOk() )
  2445. {
  2446. unsigned int i;
  2447. for ( i=0; i< strings.size(); i++ )
  2448. {
  2449. const wxString& str = strings[i];
  2450. int index = Index(str);
  2451. if ( index >= 0 )
  2452. arr.Add(index);
  2453. else if ( unmatched )
  2454. unmatched->Add(str);
  2455. }
  2456. }
  2457. return arr;
  2458. }
  2459. // -----------------------------------------------------------------------
  2460. void wxPGChoices::AllocExclusive()
  2461. {
  2462. EnsureData();
  2463. if ( m_data->GetRefCount() != 1 )
  2464. {
  2465. wxPGChoicesData* data = new wxPGChoicesData();
  2466. data->CopyDataFrom(m_data);
  2467. Free();
  2468. m_data = data;
  2469. }
  2470. }
  2471. // -----------------------------------------------------------------------
  2472. void wxPGChoices::AssignData( wxPGChoicesData* data )
  2473. {
  2474. Free();
  2475. if ( data != wxPGChoicesEmptyData )
  2476. {
  2477. m_data = data;
  2478. data->IncRef();
  2479. }
  2480. }
  2481. // -----------------------------------------------------------------------
  2482. void wxPGChoices::Init()
  2483. {
  2484. m_data = wxPGChoicesEmptyData;
  2485. }
  2486. // -----------------------------------------------------------------------
  2487. void wxPGChoices::Free()
  2488. {
  2489. if ( m_data != wxPGChoicesEmptyData )
  2490. {
  2491. m_data->DecRef();
  2492. m_data = wxPGChoicesEmptyData;
  2493. }
  2494. }
  2495. // -----------------------------------------------------------------------
  2496. // wxPGAttributeStorage
  2497. // -----------------------------------------------------------------------
  2498. wxPGAttributeStorage::wxPGAttributeStorage()
  2499. {
  2500. }
  2501. wxPGAttributeStorage::~wxPGAttributeStorage()
  2502. {
  2503. wxPGHashMapS2P::iterator it;
  2504. for ( it = m_map.begin(); it != m_map.end(); ++it )
  2505. {
  2506. wxVariantData* data = (wxVariantData*) it->second;
  2507. data->DecRef();
  2508. }
  2509. }
  2510. void wxPGAttributeStorage::Set( const wxString& name, const wxVariant& value )
  2511. {
  2512. wxVariantData* data = value.GetData();
  2513. // Free old, if any
  2514. wxPGHashMapS2P::iterator it = m_map.find(name);
  2515. if ( it != m_map.end() )
  2516. {
  2517. ((wxVariantData*)it->second)->DecRef();
  2518. if ( !data )
  2519. {
  2520. // If Null variant, just remove from set
  2521. m_map.erase(it);
  2522. return;
  2523. }
  2524. }
  2525. if ( data )
  2526. {
  2527. data->IncRef();
  2528. m_map[name] = data;
  2529. }
  2530. }
  2531. #endif // wxUSE_PROPGRID