PageRenderTime 35ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/propgrid/advprops.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 1815 lines | 1303 code | 311 blank | 201 comment | 214 complexity | 1288be686bdbd623dd51dc13456ffb19 MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/propgrid/advprops.cpp
  3. // Purpose: wxPropertyGrid Advanced Properties (font, colour, etc.)
  4. // Author: Jaakko Salli
  5. // Modified by:
  6. // Created: 2004-09-25
  7. // RCS-ID: $Id$
  8. // Copyright: (c) Jaakko Salli
  9. // Licence: wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11. // For compilers that support precompilation, includes "wx/wx.h".
  12. #include "wx/wxprec.h"
  13. #ifdef __BORLANDC__
  14. #pragma hdrstop
  15. #endif
  16. #if wxUSE_PROPGRID
  17. #ifndef WX_PRECOMP
  18. #include "wx/defs.h"
  19. #include "wx/object.h"
  20. #include "wx/hash.h"
  21. #include "wx/string.h"
  22. #include "wx/log.h"
  23. #include "wx/event.h"
  24. #include "wx/window.h"
  25. #include "wx/panel.h"
  26. #include "wx/dc.h"
  27. #include "wx/dcclient.h"
  28. #include "wx/button.h"
  29. #include "wx/pen.h"
  30. #include "wx/brush.h"
  31. #include "wx/cursor.h"
  32. #include "wx/dialog.h"
  33. #include "wx/settings.h"
  34. #include "wx/msgdlg.h"
  35. #include "wx/choice.h"
  36. #include "wx/stattext.h"
  37. #include "wx/textctrl.h"
  38. #include "wx/scrolwin.h"
  39. #include "wx/dirdlg.h"
  40. #include "wx/combobox.h"
  41. #include "wx/sizer.h"
  42. #include "wx/textdlg.h"
  43. #include "wx/filedlg.h"
  44. #include "wx/intl.h"
  45. #include "wx/wxcrtvararg.h"
  46. #endif
  47. #define __wxPG_SOURCE_FILE__
  48. #include "wx/propgrid/propgrid.h"
  49. #if wxPG_INCLUDE_ADVPROPS
  50. #include "wx/propgrid/advprops.h"
  51. #ifdef __WXMSW__
  52. #include "wx/msw/private.h"
  53. #include "wx/msw/dc.h"
  54. #endif
  55. #include "wx/odcombo.h"
  56. // -----------------------------------------------------------------------
  57. #if defined(__WXMSW__)
  58. #define wxPG_CAN_DRAW_CURSOR 1
  59. #elif defined(__WXGTK__)
  60. #define wxPG_CAN_DRAW_CURSOR 0
  61. #elif defined(__WXMAC__)
  62. #define wxPG_CAN_DRAW_CURSOR 0
  63. #else
  64. #define wxPG_CAN_DRAW_CURSOR 0
  65. #endif
  66. // -----------------------------------------------------------------------
  67. // Value type related
  68. // -----------------------------------------------------------------------
  69. // Implement dynamic class for type value.
  70. IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue, wxObject)
  71. bool operator == (const wxColourPropertyValue& a, const wxColourPropertyValue& b)
  72. {
  73. return ( ( a.m_colour == b.m_colour ) && (a.m_type == b.m_type) );
  74. }
  75. bool operator == (const wxArrayInt& array1, const wxArrayInt& array2)
  76. {
  77. if ( array1.size() != array2.size() )
  78. return false;
  79. size_t i;
  80. for ( i=0; i<array1.size(); i++ )
  81. {
  82. if ( array1[i] != array2[i] )
  83. return false;
  84. }
  85. return true;
  86. }
  87. // -----------------------------------------------------------------------
  88. // wxSpinCtrl-based property editor
  89. // -----------------------------------------------------------------------
  90. #if wxUSE_SPINBTN
  91. #ifdef __WXMSW__
  92. #define IS_MOTION_SPIN_SUPPORTED 1
  93. #else
  94. #define IS_MOTION_SPIN_SUPPORTED 0
  95. #endif
  96. #if IS_MOTION_SPIN_SUPPORTED
  97. //
  98. // This class implements ability to rapidly change "spin" value
  99. // by moving mouse when one of the spin buttons is depressed.
  100. class wxPGSpinButton : public wxSpinButton
  101. {
  102. public:
  103. wxPGSpinButton() : wxSpinButton()
  104. {
  105. m_bLeftDown = false;
  106. m_hasCapture = false;
  107. m_spins = 1;
  108. Connect( wxEVT_LEFT_DOWN,
  109. wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) );
  110. Connect( wxEVT_LEFT_UP,
  111. wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) );
  112. Connect( wxEVT_MOTION,
  113. wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) );
  114. Connect( wxEVT_MOUSE_CAPTURE_LOST,
  115. wxMouseCaptureLostEventHandler(wxPGSpinButton::OnMouseCaptureLost) );
  116. }
  117. int GetSpins() const
  118. {
  119. return m_spins;
  120. }
  121. private:
  122. wxPoint m_ptPosition;
  123. // Having a separate spins variable allows us to handle validation etc. for
  124. // multiple spin events at once (with quick mouse movements there could be
  125. // hundreds of 'spins' being done at once). Technically things like this
  126. // should be stored in event (wxSpinEvent in this case), but there probably
  127. // isn't anything there that can be reliably reused.
  128. int m_spins;
  129. bool m_bLeftDown;
  130. // SpinButton seems to be a special for mouse capture, so we may need track
  131. // privately whether mouse is actually captured.
  132. bool m_hasCapture;
  133. void Capture()
  134. {
  135. if ( !m_hasCapture )
  136. {
  137. CaptureMouse();
  138. m_hasCapture = true;
  139. }
  140. SetCursor(wxCURSOR_SIZENS);
  141. }
  142. void Release()
  143. {
  144. m_bLeftDown = false;
  145. if ( m_hasCapture )
  146. {
  147. ReleaseMouse();
  148. m_hasCapture = false;
  149. }
  150. wxWindow *parent = GetParent();
  151. if ( parent )
  152. SetCursor(parent->GetCursor());
  153. else
  154. SetCursor(wxNullCursor);
  155. }
  156. void OnMouseEvent(wxMouseEvent& event)
  157. {
  158. if ( event.GetEventType() == wxEVT_LEFT_DOWN )
  159. {
  160. m_bLeftDown = true;
  161. m_ptPosition = event.GetPosition();
  162. }
  163. else if ( event.GetEventType() == wxEVT_LEFT_UP )
  164. {
  165. Release();
  166. m_bLeftDown = false;
  167. }
  168. else if ( event.GetEventType() == wxEVT_MOTION )
  169. {
  170. if ( m_bLeftDown )
  171. {
  172. int dy = m_ptPosition.y - event.GetPosition().y;
  173. if ( dy )
  174. {
  175. Capture();
  176. m_ptPosition = event.GetPosition();
  177. wxSpinEvent evtscroll( (dy >= 0) ? wxEVT_SCROLL_LINEUP :
  178. wxEVT_SCROLL_LINEDOWN,
  179. GetId() );
  180. evtscroll.SetEventObject(this);
  181. wxASSERT( m_spins == 1 );
  182. m_spins = abs(dy);
  183. GetEventHandler()->ProcessEvent(evtscroll);
  184. m_spins = 1;
  185. }
  186. }
  187. }
  188. event.Skip();
  189. }
  190. void OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
  191. {
  192. Release();
  193. }
  194. };
  195. #endif // IS_MOTION_SPIN_SUPPORTED
  196. WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(SpinCtrl,
  197. wxPGSpinCtrlEditor,
  198. wxPGEditor)
  199. // Destructor. It is useful to reset the global pointer in it.
  200. wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor()
  201. {
  202. wxPG_EDITOR(SpinCtrl) = NULL;
  203. }
  204. // Create controls and initialize event handling.
  205. wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property,
  206. const wxPoint& pos, const wxSize& sz ) const
  207. {
  208. const int margin = 1;
  209. wxSize butSz(18, sz.y);
  210. wxSize tcSz(sz.x - butSz.x - margin, sz.y);
  211. wxPoint butPos(pos.x + tcSz.x + margin, pos.y);
  212. wxSpinButton* wnd2;
  213. #if IS_MOTION_SPIN_SUPPORTED
  214. if ( property->GetAttributeAsLong(wxT("MotionSpin"), 0) )
  215. {
  216. wnd2 = new wxPGSpinButton();
  217. }
  218. else
  219. #endif
  220. {
  221. wnd2 = new wxSpinButton();
  222. }
  223. #ifdef __WXMSW__
  224. wnd2->Hide();
  225. #endif
  226. wnd2->Create( propgrid->GetPanel(), wxPG_SUBID2, butPos, butSz, wxSP_VERTICAL );
  227. wnd2->SetRange( INT_MIN, INT_MAX );
  228. wnd2->SetValue( 0 );
  229. wxWindow* wnd1 = wxPGTextCtrlEditor::CreateControls(propgrid, property, pos, tcSz).m_primary;
  230. #if wxUSE_VALIDATORS
  231. // Let's add validator to make sure only numbers can be entered
  232. wxTextValidator validator(wxFILTER_NUMERIC, &m_tempString);
  233. wnd1->SetValidator(validator);
  234. #endif
  235. return wxPGWindowList(wnd1, wnd2);
  236. }
  237. // Control's events are redirected here
  238. bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
  239. wxWindow* wnd, wxEvent& event ) const
  240. {
  241. int evtType = event.GetEventType();
  242. int keycode = -1;
  243. int spins = 1;
  244. bool bigStep = false;
  245. if ( evtType == wxEVT_KEY_DOWN )
  246. {
  247. wxKeyEvent& keyEvent = (wxKeyEvent&)event;
  248. keycode = keyEvent.GetKeyCode();
  249. if ( keycode == WXK_UP )
  250. evtType = wxEVT_SCROLL_LINEUP;
  251. else if ( keycode == WXK_DOWN )
  252. evtType = wxEVT_SCROLL_LINEDOWN;
  253. else if ( keycode == WXK_PAGEUP )
  254. {
  255. evtType = wxEVT_SCROLL_LINEUP;
  256. bigStep = true;
  257. }
  258. else if ( keycode == WXK_PAGEDOWN )
  259. {
  260. evtType = wxEVT_SCROLL_LINEDOWN;
  261. bigStep = true;
  262. }
  263. }
  264. if ( evtType == wxEVT_SCROLL_LINEUP || evtType == wxEVT_SCROLL_LINEDOWN )
  265. {
  266. #if IS_MOTION_SPIN_SUPPORTED
  267. if ( property->GetAttributeAsLong(wxT("MotionSpin"), 0) )
  268. {
  269. wxPGSpinButton* spinButton =
  270. (wxPGSpinButton*) propgrid->GetEditorControlSecondary();
  271. if ( spinButton )
  272. spins = spinButton->GetSpins();
  273. }
  274. #endif
  275. wxString s;
  276. // Can't use wnd since it might be clipper window
  277. wxTextCtrl* tc = wxDynamicCast(propgrid->GetEditorControl(), wxTextCtrl);
  278. if ( tc )
  279. s = tc->GetValue();
  280. else
  281. s = property->GetValueAsString(wxPG_FULL_VALUE);
  282. int mode = wxPG_PROPERTY_VALIDATION_SATURATE;
  283. if ( property->GetAttributeAsLong(wxT("Wrap"), 0) )
  284. mode = wxPG_PROPERTY_VALIDATION_WRAP;
  285. if ( property->GetValueType() == wxT("double") )
  286. {
  287. double v_d;
  288. double step = property->GetAttributeAsDouble(wxT("Step"), 1.0);
  289. // Try double
  290. if ( s.ToDouble(&v_d) )
  291. {
  292. if ( bigStep )
  293. step *= 10.0;
  294. step *= (double) spins;
  295. if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += step;
  296. else v_d -= step;
  297. // Min/Max check
  298. wxFloatProperty::DoValidation(property, v_d, NULL, mode);
  299. wxPropertyGrid::DoubleToString(s, v_d, 6, true, NULL);
  300. }
  301. else
  302. {
  303. return false;
  304. }
  305. }
  306. else
  307. {
  308. wxLongLong_t v_ll;
  309. wxLongLong_t step = property->GetAttributeAsLong(wxT("Step"), 1);
  310. // Try (long) long
  311. if ( s.ToLongLong(&v_ll, 10) )
  312. {
  313. if ( bigStep )
  314. step *= 10;
  315. step *= spins;
  316. if ( evtType == wxEVT_SCROLL_LINEUP ) v_ll += step;
  317. else v_ll -= step;
  318. // Min/Max check
  319. wxIntProperty::DoValidation(property, v_ll, NULL, mode);
  320. s = wxLongLong(v_ll).ToString();
  321. }
  322. else
  323. {
  324. return false;
  325. }
  326. }
  327. if ( tc )
  328. {
  329. int ip = tc->GetInsertionPoint();
  330. int lp = tc->GetLastPosition();
  331. tc->SetValue(s);
  332. tc->SetInsertionPoint(ip+(tc->GetLastPosition()-lp));
  333. }
  334. return true;
  335. }
  336. return wxPGTextCtrlEditor::OnEvent(propgrid,property,wnd,event);
  337. }
  338. #endif // wxUSE_SPINBTN
  339. // -----------------------------------------------------------------------
  340. // wxDatePickerCtrl-based property editor
  341. // -----------------------------------------------------------------------
  342. #if wxUSE_DATEPICKCTRL
  343. #include "wx/datectrl.h"
  344. #include "wx/dateevt.h"
  345. class wxPGDatePickerCtrlEditor : public wxPGEditor
  346. {
  347. DECLARE_DYNAMIC_CLASS(wxPGDatePickerCtrlEditor)
  348. public:
  349. virtual ~wxPGDatePickerCtrlEditor();
  350. wxString GetName() const;
  351. virtual wxPGWindowList CreateControls(wxPropertyGrid* propgrid,
  352. wxPGProperty* property,
  353. const wxPoint& pos,
  354. const wxSize& size) const;
  355. virtual void UpdateControl( wxPGProperty* property, wxWindow* wnd ) const;
  356. virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
  357. wxWindow* wnd, wxEvent& event ) const;
  358. virtual bool GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* wnd ) const;
  359. virtual void SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const;
  360. };
  361. WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(DatePickerCtrl,
  362. wxPGDatePickerCtrlEditor,
  363. wxPGEditor)
  364. wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor()
  365. {
  366. wxPG_EDITOR(DatePickerCtrl) = NULL;
  367. }
  368. wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid,
  369. wxPGProperty* property,
  370. const wxPoint& pos,
  371. const wxSize& sz ) const
  372. {
  373. wxCHECK_MSG( property->IsKindOf(CLASSINFO(wxDateProperty)),
  374. NULL,
  375. wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") );
  376. wxDateProperty* prop = wxDynamicCast(property, wxDateProperty);
  377. // Use two stage creation to allow cleaner display on wxMSW
  378. wxDatePickerCtrl* ctrl = new wxDatePickerCtrl();
  379. #ifdef __WXMSW__
  380. ctrl->Hide();
  381. wxSize useSz = wxDefaultSize;
  382. useSz.x = sz.x;
  383. #else
  384. wxSize useSz = sz;
  385. #endif
  386. wxDateTime dateValue(wxInvalidDateTime);
  387. wxVariant value = prop->GetValue();
  388. if ( value.GetType() == wxT("datetime") )
  389. dateValue = value.GetDateTime();
  390. ctrl->Create(propgrid->GetPanel(),
  391. wxPG_SUBID1,
  392. dateValue,
  393. pos,
  394. useSz,
  395. prop->GetDatePickerStyle() | wxNO_BORDER);
  396. #ifdef __WXMSW__
  397. ctrl->Show();
  398. #endif
  399. return ctrl;
  400. }
  401. // Copies value from property to control
  402. void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty* property,
  403. wxWindow* wnd ) const
  404. {
  405. wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
  406. wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
  407. wxDateTime dateValue(wxInvalidDateTime);
  408. wxVariant v(property->GetValue());
  409. if ( v.GetType() == wxT("datetime") )
  410. dateValue = v.GetDateTime();
  411. ctrl->SetValue( dateValue );
  412. }
  413. // Control's events are redirected here
  414. bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid* WXUNUSED(propgrid),
  415. wxPGProperty* WXUNUSED(property),
  416. wxWindow* WXUNUSED(wnd),
  417. wxEvent& event ) const
  418. {
  419. if ( event.GetEventType() == wxEVT_DATE_CHANGED )
  420. return true;
  421. return false;
  422. }
  423. bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const
  424. {
  425. wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
  426. wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
  427. variant = ctrl->GetValue();
  428. return true;
  429. }
  430. void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* property,
  431. wxWindow* wnd ) const
  432. {
  433. wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
  434. wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
  435. wxDateProperty* prop = wxDynamicCast(property, wxDateProperty);
  436. if ( prop )
  437. {
  438. int datePickerStyle = prop->GetDatePickerStyle();
  439. if ( datePickerStyle & wxDP_ALLOWNONE )
  440. ctrl->SetValue(wxInvalidDateTime);
  441. }
  442. }
  443. #endif // wxUSE_DATEPICKCTRL
  444. // -----------------------------------------------------------------------
  445. // wxFontProperty
  446. // -----------------------------------------------------------------------
  447. #include "wx/fontdlg.h"
  448. #include "wx/fontenum.h"
  449. //
  450. // NB: Do not use wxS here since unlike wxT it doesn't translate to wxChar*
  451. //
  452. static const wxChar* const gs_fp_es_family_labels[] = {
  453. wxT("Default"), wxT("Decorative"),
  454. wxT("Roman"), wxT("Script"),
  455. wxT("Swiss"), wxT("Modern"),
  456. wxT("Teletype"), wxT("Unknown"),
  457. (const wxChar*) NULL
  458. };
  459. static const long gs_fp_es_family_values[] = {
  460. wxFONTFAMILY_DEFAULT, wxFONTFAMILY_DECORATIVE,
  461. wxFONTFAMILY_ROMAN, wxFONTFAMILY_SCRIPT,
  462. wxFONTFAMILY_SWISS, wxFONTFAMILY_MODERN,
  463. wxFONTFAMILY_TELETYPE, wxFONTFAMILY_UNKNOWN
  464. };
  465. static const wxChar* const gs_fp_es_style_labels[] = {
  466. wxT("Normal"),
  467. wxT("Slant"),
  468. wxT("Italic"),
  469. (const wxChar*) NULL
  470. };
  471. static const long gs_fp_es_style_values[] = {
  472. wxNORMAL,
  473. wxSLANT,
  474. wxITALIC
  475. };
  476. static const wxChar* const gs_fp_es_weight_labels[] = {
  477. wxT("Normal"),
  478. wxT("Light"),
  479. wxT("Bold"),
  480. (const wxChar*) NULL
  481. };
  482. static const long gs_fp_es_weight_values[] = {
  483. wxNORMAL,
  484. wxLIGHT,
  485. wxBOLD
  486. };
  487. // Class body is in advprops.h
  488. WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty,wxPGProperty,
  489. wxFont,const wxFont&,TextCtrlAndButton)
  490. wxFontProperty::wxFontProperty( const wxString& label, const wxString& name,
  491. const wxFont& value )
  492. : wxPGProperty(label,name)
  493. {
  494. SetValue(WXVARIANT(value));
  495. // Initialize font family choices list
  496. if ( !wxPGGlobalVars->m_fontFamilyChoices )
  497. {
  498. wxArrayString faceNames = wxFontEnumerator::GetFacenames();
  499. faceNames.Sort();
  500. wxPGGlobalVars->m_fontFamilyChoices = new wxPGChoices(faceNames);
  501. }
  502. wxString emptyString(wxEmptyString);
  503. wxFont font;
  504. font << m_value;
  505. AddPrivateChild( new wxIntProperty( _("Point Size"),
  506. wxS("Point Size"),(long)font.GetPointSize() ) );
  507. wxString faceName = font.GetFaceName();
  508. // If font was not in there, add it now
  509. if ( !faceName.empty() &&
  510. wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND )
  511. wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName);
  512. wxPGProperty* p = new wxEnumProperty(_("Face Name"), wxS("Face Name"),
  513. *wxPGGlobalVars->m_fontFamilyChoices);
  514. p->SetValueFromString(faceName, wxPG_FULL_VALUE);
  515. AddPrivateChild( p );
  516. AddPrivateChild( new wxEnumProperty(_("Style"), wxS("Style"),
  517. gs_fp_es_style_labels,gs_fp_es_style_values,
  518. font.GetStyle()) );
  519. AddPrivateChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
  520. gs_fp_es_weight_labels,gs_fp_es_weight_values,
  521. font.GetWeight()) );
  522. AddPrivateChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
  523. font.GetUnderlined()) );
  524. AddPrivateChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
  525. gs_fp_es_family_labels,gs_fp_es_family_values,
  526. font.GetFamily()) );
  527. }
  528. wxFontProperty::~wxFontProperty() { }
  529. void wxFontProperty::OnSetValue()
  530. {
  531. wxFont font;
  532. font << m_value;
  533. if ( !font.IsOk() )
  534. {
  535. m_value << *wxNORMAL_FONT;
  536. }
  537. }
  538. wxString wxFontProperty::ValueToString( wxVariant& value,
  539. int argFlags ) const
  540. {
  541. return wxPGProperty::ValueToString(value, argFlags);
  542. }
  543. bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary),
  544. wxEvent& event )
  545. {
  546. if ( propgrid->IsMainButtonEvent(event) )
  547. {
  548. // Update value from last minute changes
  549. wxVariant useValue = propgrid->GetUncommittedPropertyValue();
  550. wxFontData data;
  551. wxFont font;
  552. if ( useValue.GetType() == wxS("wxFont") )
  553. font << useValue;
  554. data.SetInitialFont( font );
  555. data.SetColour(*wxBLACK);
  556. wxFontDialog dlg(propgrid, data);
  557. if ( dlg.ShowModal() == wxID_OK )
  558. {
  559. propgrid->EditorsValueWasModified();
  560. wxVariant variant;
  561. variant << dlg.GetFontData().GetChosenFont();
  562. SetValueInEvent( variant );
  563. return true;
  564. }
  565. }
  566. return false;
  567. }
  568. void wxFontProperty::RefreshChildren()
  569. {
  570. if ( !GetChildCount() ) return;
  571. wxFont font;
  572. font << m_value;
  573. Item(0)->SetValue( (long)font.GetPointSize() );
  574. Item(1)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE );
  575. Item(2)->SetValue( (long)font.GetStyle() );
  576. Item(3)->SetValue( (long)font.GetWeight() );
  577. Item(4)->SetValue( font.GetUnderlined() );
  578. Item(5)->SetValue( (long)font.GetFamily() );
  579. }
  580. wxVariant wxFontProperty::ChildChanged( wxVariant& thisValue,
  581. int ind,
  582. wxVariant& childValue ) const
  583. {
  584. wxFont font;
  585. font << thisValue;
  586. if ( ind == 0 )
  587. {
  588. font.SetPointSize( childValue.GetLong() );
  589. }
  590. else if ( ind == 1 )
  591. {
  592. wxString faceName;
  593. int faceIndex = childValue.GetLong();
  594. if ( faceIndex >= 0 )
  595. faceName = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(faceIndex);
  596. font.SetFaceName( faceName );
  597. }
  598. else if ( ind == 2 )
  599. {
  600. int st = childValue.GetLong();
  601. if ( st != wxFONTSTYLE_NORMAL &&
  602. st != wxFONTSTYLE_SLANT &&
  603. st != wxFONTSTYLE_ITALIC )
  604. st = wxFONTWEIGHT_NORMAL;
  605. font.SetStyle( st );
  606. }
  607. else if ( ind == 3 )
  608. {
  609. int wt = childValue.GetLong();
  610. if ( wt != wxFONTWEIGHT_NORMAL &&
  611. wt != wxFONTWEIGHT_LIGHT &&
  612. wt != wxFONTWEIGHT_BOLD )
  613. wt = wxFONTWEIGHT_NORMAL;
  614. font.SetWeight( wt );
  615. }
  616. else if ( ind == 4 )
  617. {
  618. font.SetUnderlined( childValue.GetBool() );
  619. }
  620. else if ( ind == 5 )
  621. {
  622. int fam = childValue.GetLong();
  623. if ( fam < wxDEFAULT ||
  624. fam > wxTELETYPE )
  625. fam = wxDEFAULT;
  626. font.SetFamily( fam );
  627. }
  628. wxVariant newVariant;
  629. newVariant << font;
  630. return newVariant;
  631. }
  632. /*
  633. wxSize wxFontProperty::OnMeasureImage() const
  634. {
  635. return wxSize(-1,-1);
  636. }
  637. void wxFontProperty::OnCustomPaint(wxDC& dc,
  638. const wxRect& rect,
  639. wxPGPaintData& paintData)
  640. {
  641. wxString drawFace;
  642. if ( paintData.m_choiceItem >= 0 )
  643. drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
  644. else
  645. drawFace = m_value_wxFont.GetFaceName();
  646. if ( !drawFace.empty() )
  647. {
  648. // Draw the background
  649. dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
  650. //dc.SetBrush( *wxWHITE_BRUSH );
  651. //dc.SetPen( *wxMEDIUM_GREY_PEN );
  652. dc.DrawRectangle( rect );
  653. wxFont oldFont = dc.GetFont();
  654. wxFont drawFont(oldFont.GetPointSize(),
  655. wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
  656. dc.SetFont(drawFont);
  657. dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
  658. dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
  659. dc.SetFont(oldFont);
  660. }
  661. else
  662. {
  663. // No file - just draw a white box
  664. dc.SetBrush ( *wxWHITE_BRUSH );
  665. dc.DrawRectangle ( rect );
  666. }
  667. }
  668. */
  669. // -----------------------------------------------------------------------
  670. // wxSystemColourProperty
  671. // -----------------------------------------------------------------------
  672. // wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
  673. #define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
  674. #include "wx/colordlg.h"
  675. //#define wx_cp_es_syscolours_len 25
  676. static const wxChar* const gs_cp_es_syscolour_labels[] = {
  677. wxT("AppWorkspace"),
  678. wxT("ActiveBorder"),
  679. wxT("ActiveCaption"),
  680. wxT("ButtonFace"),
  681. wxT("ButtonHighlight"),
  682. wxT("ButtonShadow"),
  683. wxT("ButtonText"),
  684. wxT("CaptionText"),
  685. wxT("ControlDark"),
  686. wxT("ControlLight"),
  687. wxT("Desktop"),
  688. wxT("GrayText"),
  689. wxT("Highlight"),
  690. wxT("HighlightText"),
  691. wxT("InactiveBorder"),
  692. wxT("InactiveCaption"),
  693. wxT("InactiveCaptionText"),
  694. wxT("Menu"),
  695. wxT("Scrollbar"),
  696. wxT("Tooltip"),
  697. wxT("TooltipText"),
  698. wxT("Window"),
  699. wxT("WindowFrame"),
  700. wxT("WindowText"),
  701. wxT("Custom"),
  702. (const wxChar*) NULL
  703. };
  704. static const long gs_cp_es_syscolour_values[] = {
  705. wxSYS_COLOUR_APPWORKSPACE,
  706. wxSYS_COLOUR_ACTIVEBORDER,
  707. wxSYS_COLOUR_ACTIVECAPTION,
  708. wxSYS_COLOUR_BTNFACE,
  709. wxSYS_COLOUR_BTNHIGHLIGHT,
  710. wxSYS_COLOUR_BTNSHADOW,
  711. wxSYS_COLOUR_BTNTEXT ,
  712. wxSYS_COLOUR_CAPTIONTEXT,
  713. wxSYS_COLOUR_3DDKSHADOW,
  714. wxSYS_COLOUR_3DLIGHT,
  715. wxSYS_COLOUR_BACKGROUND,
  716. wxSYS_COLOUR_GRAYTEXT,
  717. wxSYS_COLOUR_HIGHLIGHT,
  718. wxSYS_COLOUR_HIGHLIGHTTEXT,
  719. wxSYS_COLOUR_INACTIVEBORDER,
  720. wxSYS_COLOUR_INACTIVECAPTION,
  721. wxSYS_COLOUR_INACTIVECAPTIONTEXT,
  722. wxSYS_COLOUR_MENU,
  723. wxSYS_COLOUR_SCROLLBAR,
  724. wxSYS_COLOUR_INFOBK,
  725. wxSYS_COLOUR_INFOTEXT,
  726. wxSYS_COLOUR_WINDOW,
  727. wxSYS_COLOUR_WINDOWFRAME,
  728. wxSYS_COLOUR_WINDOWTEXT,
  729. wxPG_COLOUR_CUSTOM
  730. };
  731. IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue, WXDLLIMPEXP_PROPGRID)
  732. // Class body is in advprops.h
  733. WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty,
  734. wxColourPropertyValue,const wxColourPropertyValue&,Choice)
  735. void wxSystemColourProperty::Init( int type, const wxColour& colour )
  736. {
  737. wxColourPropertyValue cpv;
  738. if ( colour.IsOk() )
  739. cpv.Init( type, colour );
  740. else
  741. cpv.Init( type, *wxWHITE );
  742. m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed.
  743. m_value << cpv;
  744. OnSetValue();
  745. }
  746. static wxPGChoices gs_wxSystemColourProperty_choicesCache;
  747. wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
  748. const wxColourPropertyValue& value )
  749. : wxEnumProperty( label,
  750. name,
  751. gs_cp_es_syscolour_labels,
  752. gs_cp_es_syscolour_values,
  753. &gs_wxSystemColourProperty_choicesCache )
  754. {
  755. if ( &value )
  756. Init( value.m_type, value.m_colour );
  757. else
  758. Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
  759. }
  760. wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
  761. const wxChar* const* labels, const long* values, wxPGChoices* choicesCache,
  762. const wxColourPropertyValue& value )
  763. : wxEnumProperty( label, name, labels, values, choicesCache )
  764. {
  765. if ( &value )
  766. Init( value.m_type, value.m_colour );
  767. else
  768. Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
  769. }
  770. wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
  771. const wxChar* const* labels, const long* values, wxPGChoices* choicesCache,
  772. const wxColour& value )
  773. : wxEnumProperty( label, name, labels, values, choicesCache )
  774. {
  775. if ( &value )
  776. Init( wxPG_COLOUR_CUSTOM, value );
  777. else
  778. Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
  779. }
  780. wxSystemColourProperty::~wxSystemColourProperty() { }
  781. wxColourPropertyValue wxSystemColourProperty::GetVal( const wxVariant* pVariant ) const
  782. {
  783. if ( !pVariant )
  784. pVariant = &m_value;
  785. if ( pVariant->IsNull() )
  786. return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
  787. if ( pVariant->GetType() == wxS("wxColourPropertyValue") )
  788. {
  789. wxColourPropertyValue v;
  790. v << *pVariant;
  791. return v;
  792. }
  793. wxColour col;
  794. bool variantProcessed = true;
  795. if ( pVariant->GetType() == wxS("wxColour*") )
  796. {
  797. wxColour* pCol = wxStaticCast(pVariant->GetWxObjectPtr(), wxColour);
  798. col = *pCol;
  799. }
  800. else if ( pVariant->GetType() == wxS("wxColour") )
  801. {
  802. col << *pVariant;
  803. }
  804. else if ( pVariant->GetType() == wxArrayInt_VariantType )
  805. {
  806. // This code is mostly needed for wxPython bindings, which
  807. // may offer tuple of integers as colour value.
  808. wxArrayInt arr;
  809. arr << *pVariant;
  810. if ( arr.size() >= 3 )
  811. {
  812. int r, g, b;
  813. int a = 255;
  814. r = arr[0];
  815. g = arr[1];
  816. b = arr[2];
  817. if ( arr.size() >= 4 )
  818. a = arr[3];
  819. col = wxColour(r, g, b, a);
  820. }
  821. else
  822. {
  823. variantProcessed = false;
  824. }
  825. }
  826. else
  827. {
  828. variantProcessed = false;
  829. }
  830. if ( !variantProcessed )
  831. return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
  832. wxColourPropertyValue v2( wxPG_COLOUR_CUSTOM, col );
  833. int colInd = ColToInd(col);
  834. if ( colInd != wxNOT_FOUND )
  835. v2.m_type = colInd;
  836. return v2;
  837. }
  838. wxVariant wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
  839. {
  840. wxVariant variant;
  841. variant << v;
  842. return variant;
  843. }
  844. int wxSystemColourProperty::ColToInd( const wxColour& colour ) const
  845. {
  846. size_t i;
  847. size_t i_max = m_choices.GetCount();
  848. if ( !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
  849. i_max -= 1;
  850. for ( i=0; i<i_max; i++ )
  851. {
  852. int ind = m_choices[i].GetValue();
  853. if ( colour == GetColour(ind) )
  854. {
  855. /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
  856. GetClassName(),GetLabel().c_str(),
  857. (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
  858. (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
  859. return ind;
  860. }
  861. }
  862. return wxNOT_FOUND;
  863. }
  864. void wxSystemColourProperty::OnSetValue()
  865. {
  866. // Convert from generic wxobject ptr to wxPGVariantDataColour
  867. if ( m_value.GetType() == wxS("wxColour*") )
  868. {
  869. wxColour* pCol = wxStaticCast(m_value.GetWxObjectPtr(), wxColour);
  870. m_value << *pCol;
  871. }
  872. wxColourPropertyValue val = GetVal(&m_value);
  873. if ( val.m_type == wxPG_COLOUR_UNSPECIFIED )
  874. {
  875. m_value.MakeNull();
  876. return;
  877. }
  878. else
  879. {
  880. if ( val.m_type < wxPG_COLOUR_WEB_BASE )
  881. val.m_colour = GetColour( val.m_type );
  882. m_value = TranslateVal(val);
  883. }
  884. int ind = wxNOT_FOUND;
  885. if ( m_value.GetType() == wxS("wxColourPropertyValue") )
  886. {
  887. wxColourPropertyValue cpv;
  888. cpv << m_value;
  889. wxColour col = cpv.m_colour;
  890. if ( !col.IsOk() )
  891. {
  892. SetValueToUnspecified();
  893. SetIndex(wxNOT_FOUND);
  894. return;
  895. }
  896. if ( cpv.m_type < wxPG_COLOUR_WEB_BASE ||
  897. (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
  898. {
  899. ind = GetIndexForValue(cpv.m_type);
  900. }
  901. else
  902. {
  903. cpv.m_type = wxPG_COLOUR_CUSTOM;
  904. ind = GetCustomColourIndex();
  905. }
  906. }
  907. else
  908. {
  909. wxColour col;
  910. col << m_value;
  911. if ( !col.IsOk() )
  912. {
  913. SetValueToUnspecified();
  914. SetIndex(wxNOT_FOUND);
  915. return;
  916. }
  917. ind = ColToInd(col);
  918. if ( ind == wxNOT_FOUND &&
  919. !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
  920. ind = GetCustomColourIndex();
  921. }
  922. SetIndex(ind);
  923. }
  924. wxColour wxSystemColourProperty::GetColour( int index ) const
  925. {
  926. return wxSystemSettings::GetColour( (wxSystemColour)index );
  927. }
  928. wxString wxSystemColourProperty::ColourToString( const wxColour& col,
  929. int index,
  930. int argFlags ) const
  931. {
  932. if ( index == wxNOT_FOUND )
  933. {
  934. if ( (argFlags & wxPG_FULL_VALUE) ||
  935. GetAttributeAsLong(wxPG_COLOUR_HAS_ALPHA, 0) )
  936. {
  937. return wxString::Format(wxS("(%i,%i,%i,%i)"),
  938. (int)col.Red(),
  939. (int)col.Green(),
  940. (int)col.Blue(),
  941. (int)col.Alpha());
  942. }
  943. else
  944. {
  945. return wxString::Format(wxS("(%i,%i,%i)"),
  946. (int)col.Red(),
  947. (int)col.Green(),
  948. (int)col.Blue());
  949. }
  950. }
  951. else
  952. {
  953. return m_choices.GetLabel(index);
  954. }
  955. }
  956. wxString wxSystemColourProperty::ValueToString( wxVariant& value,
  957. int argFlags ) const
  958. {
  959. wxColourPropertyValue val = GetVal(&value);
  960. int index;
  961. if ( argFlags & wxPG_VALUE_IS_CURRENT )
  962. {
  963. // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
  964. // but we should use it whenever possible.
  965. index = GetIndex();
  966. // If custom colour was selected, use invalid index, so that
  967. // ColourToString() will return properly formatted colour text.
  968. if ( index == GetCustomColourIndex() &&
  969. !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
  970. index = wxNOT_FOUND;
  971. }
  972. else
  973. {
  974. index = m_choices.Index(val.m_type);
  975. }
  976. return ColourToString(val.m_colour, index, argFlags);
  977. }
  978. wxSize wxSystemColourProperty::OnMeasureImage( int ) const
  979. {
  980. return wxPG_DEFAULT_IMAGE_SIZE;
  981. }
  982. int wxSystemColourProperty::GetCustomColourIndex() const
  983. {
  984. return m_choices.GetCount() - 1;
  985. }
  986. bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const
  987. {
  988. wxASSERT( m_value.GetType() != wxPG_VARIANT_TYPE_STRING );
  989. bool res = false;
  990. wxPropertyGrid* propgrid = GetGrid();
  991. wxASSERT( propgrid );
  992. // Must only occur when user triggers event
  993. if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT) )
  994. return res;
  995. wxColourPropertyValue val = GetVal();
  996. val.m_type = wxPG_COLOUR_CUSTOM;
  997. wxColourData data;
  998. data.SetChooseFull(true);
  999. data.SetColour(val.m_colour);
  1000. int i;
  1001. for ( i = 0; i < 16; i++)
  1002. {
  1003. wxColour colour(i*16, i*16, i*16);
  1004. data.SetCustomColour(i, colour);
  1005. }
  1006. wxColourDialog dialog(propgrid, &data);
  1007. if ( dialog.ShowModal() == wxID_OK )
  1008. {
  1009. wxColourData retData = dialog.GetColourData();
  1010. val.m_colour = retData.GetColour();
  1011. variant = DoTranslateVal(val);
  1012. SetValueInEvent(variant);
  1013. res = true;
  1014. }
  1015. return res;
  1016. }
  1017. bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
  1018. {
  1019. int index = number;
  1020. int type = m_choices.GetValue(index);
  1021. if ( type == wxPG_COLOUR_CUSTOM )
  1022. {
  1023. QueryColourFromUser(variant);
  1024. }
  1025. else
  1026. {
  1027. variant = TranslateVal( type, GetColour(type) );
  1028. }
  1029. return true;
  1030. }
  1031. // Need to do some extra event handling.
  1032. bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid,
  1033. wxWindow* WXUNUSED(primary),
  1034. wxEvent& event )
  1035. {
  1036. bool askColour = false;
  1037. if ( propgrid->IsMainButtonEvent(event) )
  1038. {
  1039. // We need to handle button click in case editor has been
  1040. // switched to one that has wxButton as well.
  1041. askColour = true;
  1042. }
  1043. else if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
  1044. {
  1045. // Must override index detection since at this point GetIndex()
  1046. // will return old value.
  1047. wxOwnerDrawnComboBox* cb =
  1048. static_cast<wxOwnerDrawnComboBox*>(propgrid->GetEditorControl());
  1049. if ( cb )
  1050. {
  1051. int index = cb->GetSelection();
  1052. if ( index == GetCustomColourIndex() &&
  1053. !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
  1054. askColour = true;
  1055. }
  1056. }
  1057. if ( askColour && !propgrid->WasValueChangedInEvent() )
  1058. {
  1059. wxVariant variant;
  1060. if ( QueryColourFromUser(variant) )
  1061. return true;
  1062. }
  1063. return false;
  1064. }
  1065. /*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
  1066. {
  1067. public:
  1068. virtual void Render( wxDC& dc, const wxRect& rect,
  1069. const wxPropertyGrid* propertyGrid, wxPGProperty* property,
  1070. int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
  1071. {
  1072. wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
  1073. wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
  1074. dc.SetPen(*wxBLACK_PEN);
  1075. if ( item >= 0 &&
  1076. ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
  1077. )
  1078. {
  1079. int colInd;
  1080. const wxArrayInt& values = prop->GetValues();
  1081. if ( values.GetChildCount() )
  1082. colInd = values[item];
  1083. else
  1084. colInd = item;
  1085. dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
  1086. }
  1087. else if ( !prop->IsValueUnspecified() )
  1088. dc.SetBrush( prop->GetVal().m_colour );
  1089. else
  1090. dc.SetBrush( *wxWHITE );
  1091. wxRect imageRect = propertyGrid->GetImageRect(property, item);
  1092. wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
  1093. dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
  1094. imageRect.width, imageRect.height );
  1095. wxString text;
  1096. if ( item == -1 )
  1097. text = property->GetValueAsString();
  1098. else
  1099. text = property->GetChoiceString(item);
  1100. DrawText( dc, rect, imageRect.width, text );
  1101. }
  1102. protected:
  1103. };
  1104. wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
  1105. wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
  1106. {
  1107. if ( column == 1 )
  1108. return &g_wxPGColourPropertyRenderer;
  1109. return wxEnumProperty::GetCellRenderer(column);
  1110. }*/
  1111. void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect,
  1112. wxPGPaintData& paintdata )
  1113. {
  1114. wxColour col;
  1115. if ( paintdata.m_choiceItem >= 0 &&
  1116. paintdata.m_choiceItem < (int)m_choices.GetCount() &&
  1117. (paintdata.m_choiceItem != GetCustomColourIndex() ||
  1118. m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
  1119. {
  1120. int colInd = m_choices[paintdata.m_choiceItem].GetValue();
  1121. col = GetColour( colInd );
  1122. }
  1123. else if ( !IsValueUnspecified() )
  1124. {
  1125. col = GetVal().m_colour;
  1126. }
  1127. if ( col.IsOk() )
  1128. {
  1129. dc.SetBrush(col);
  1130. dc.DrawRectangle(rect);
  1131. }
  1132. }
  1133. bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const
  1134. {
  1135. wxString custColName(m_choices.GetLabel(GetCustomColourIndex()));
  1136. wxString colStr(text);
  1137. colStr.Trim(true);
  1138. colStr.Trim(false);
  1139. wxColour customColour;
  1140. bool conversionSuccess = false;
  1141. if ( colStr != custColName )
  1142. {
  1143. if ( colStr.Find(wxS("(")) == 0 )
  1144. {
  1145. // Eliminate whitespace
  1146. colStr.Replace(wxS(" "), wxEmptyString);
  1147. int commaCount = colStr.Freq(wxS(','));
  1148. if ( commaCount == 2 )
  1149. {
  1150. // Convert (R,G,B) to rgb(R,G,B)
  1151. colStr = wxS("rgb") + colStr;
  1152. }
  1153. else if ( commaCount == 3 )
  1154. {
  1155. // We have int alpha, CSS format that wxColour takes as
  1156. // input processes float alpha. So, let's parse the colour
  1157. // ourselves instead of trying to convert it to a format
  1158. // that wxColour::FromString() understands.
  1159. int r = -1, g = -1, b = -1, a = -1;
  1160. wxSscanf(colStr, wxS("(%i,%i,%i,%i)"), &r, &g, &b, &a);
  1161. customColour.Set(r, g, b, a);
  1162. conversionSuccess = customColour.IsOk();
  1163. }
  1164. }
  1165. if ( !conversionSuccess )
  1166. conversionSuccess = customColour.Set(colStr);
  1167. }
  1168. if ( !conversionSuccess && m_choices.GetCount() &&
  1169. !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) &&
  1170. colStr == custColName )
  1171. {
  1172. if ( !(argFlags & wxPG_EDITABLE_VALUE ))
  1173. {
  1174. // This really should not occurr...
  1175. // wxASSERT(false);
  1176. ResetNextIndex();
  1177. return false;
  1178. }
  1179. QueryColourFromUser(value);
  1180. }
  1181. else
  1182. {
  1183. wxColourPropertyValue val;
  1184. bool done = false;
  1185. if ( !conversionSuccess )
  1186. {
  1187. // Try predefined colour first
  1188. bool res = wxEnumProperty::StringToValue(value,
  1189. colStr,
  1190. argFlags);
  1191. if ( res && GetIndex() >= 0 )
  1192. {
  1193. val.m_type = GetIndex();
  1194. if ( val.m_type < m_choices.GetCount() )
  1195. val.m_type = m_choices[val.m_type].GetValue();
  1196. // Get proper colour for type.
  1197. val.m_colour = GetColour(val.m_type);
  1198. done = true;
  1199. }
  1200. }
  1201. else
  1202. {
  1203. val.m_type = wxPG_COLOUR_CUSTOM;
  1204. val.m_colour = customColour;
  1205. done = true;
  1206. }
  1207. if ( !done )
  1208. {
  1209. ResetNextIndex();
  1210. return false;
  1211. }
  1212. value = DoTranslateVal(val);
  1213. }
  1214. return true;
  1215. }
  1216. bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& value )
  1217. {
  1218. if ( name == wxPG_COLOUR_ALLOW_CUSTOM )
  1219. {
  1220. int ival = value.GetLong();
  1221. if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
  1222. {
  1223. // Show custom choice
  1224. m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM);
  1225. m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
  1226. }
  1227. else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
  1228. {
  1229. // Hide custom choice
  1230. m_choices.RemoveAt(GetCustomColourIndex());
  1231. m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
  1232. }
  1233. return true;
  1234. }
  1235. return false;
  1236. }
  1237. // -----------------------------------------------------------------------
  1238. // wxColourProperty
  1239. // -----------------------------------------------------------------------
  1240. static const wxChar* const gs_cp_es_normcolour_labels[] = {
  1241. wxT("Black"),
  1242. wxT("Maroon"),
  1243. wxT("Navy"),
  1244. wxT("Purple"),
  1245. wxT("Teal"),
  1246. wxT("Gray"),
  1247. wxT("Green"),
  1248. wxT("Olive"),
  1249. wxT("Brown"),
  1250. wxT("Blue"),
  1251. wxT("Fuchsia"),
  1252. wxT("Red"),
  1253. wxT("Orange"),
  1254. wxT("Silver"),
  1255. wxT("Lime"),
  1256. wxT("Aqua"),
  1257. wxT("Yellow"),
  1258. wxT("White"),
  1259. wxT("Custom"),
  1260. (const wxChar*) NULL
  1261. };
  1262. static const unsigned long gs_cp_es_normcolour_colours[] = {
  1263. wxPG_COLOUR(0,0,0),
  1264. wxPG_COLOUR(128,0,0),
  1265. wxPG_COLOUR(0,0,128),
  1266. wxPG_COLOUR(128,0,128),
  1267. wxPG_COLOUR(0,128,128),
  1268. wxPG_COLOUR(128,128,128),
  1269. wxPG_COLOUR(0,128,0),
  1270. wxPG_COLOUR(128,128,0),
  1271. wxPG_COLOUR(166,124,81),
  1272. wxPG_COLOUR(0,0,255),
  1273. wxPG_COLOUR(255,0,255),
  1274. wxPG_COLOUR(255,0,0),
  1275. wxPG_COLOUR(247,148,28),
  1276. wxPG_COLOUR(192,192,192),
  1277. wxPG_COLOUR(0,255,0),
  1278. wxPG_COLOUR(0,255,255),
  1279. wxPG_COLOUR(255,255,0),
  1280. wxPG_COLOUR(255,255,255),
  1281. wxPG_COLOUR(0,0,0)
  1282. };
  1283. WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty,
  1284. wxColour, const wxColour&, TextCtrlAndButton)
  1285. static wxPGChoices gs_wxColourProperty_choicesCache;
  1286. wxColourProperty::wxColourProperty( const wxString& label,
  1287. const wxString& name,
  1288. const wxColour& value )
  1289. : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels,
  1290. NULL,
  1291. &gs_wxColourProperty_choicesCache, value )
  1292. {
  1293. Init( value );
  1294. m_flags |= wxPG_PROP_TRANSLATE_CUSTOM;
  1295. }
  1296. wxColourProperty::~wxColourProperty()
  1297. {
  1298. }
  1299. void wxColourProperty::Init( wxColour colour )
  1300. {
  1301. if ( !colour.IsOk() )
  1302. colour = *wxWHITE;
  1303. wxVariant variant;
  1304. variant << colour;
  1305. m_value = variant;
  1306. int ind = ColToInd(colour);
  1307. if ( ind < 0 )
  1308. ind = m_choices.GetCount() - 1;
  1309. SetIndex( ind );
  1310. }
  1311. wxString wxColourProperty::ValueToString( wxVariant& value,
  1312. int argFlags ) const
  1313. {
  1314. const wxPGEditor* editor = GetEditorClass();
  1315. if ( editor != wxPGEditor_Choice &&
  1316. editor != wxPGEditor_ChoiceAndButton &&
  1317. editor != wxPGEditor_ComboBox )
  1318. argFlags |= wxPG_PROPERTY_SPECIFIC;
  1319. return wxSystemColourProperty::ValueToString(value, argFlags);
  1320. }
  1321. wxColour wxColourProperty::GetColour( int index ) const
  1322. {
  1323. return gs_cp_es_normcolour_colours[m_choices.GetValue(index)];
  1324. }
  1325. wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
  1326. {
  1327. wxVariant variant;
  1328. variant << v.m_colour;
  1329. return variant;
  1330. }
  1331. // -----------------------------------------------------------------------
  1332. // wxCursorProperty
  1333. // -----------------------------------------------------------------------
  1334. #define wxPG_CURSOR_IMAGE_WIDTH 32
  1335. #define NUM_CURSORS 28
  1336. //#define wx_cp_es_syscursors_len 28
  1337. static const wxChar* const gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
  1338. wxT("Default"),
  1339. wxT("Arrow"),
  1340. wxT("Right Arrow"),
  1341. wxT("Blank"),
  1342. wxT("Bullseye"),
  1343. wxT("Character"),
  1344. wxT("Cross"),
  1345. wxT("Hand"),
  1346. wxT("I-Beam"),
  1347. wxT("Left Button"),
  1348. wxT("Magnifier"),
  1349. wxT("Middle Button"),
  1350. wxT("No Entry"),
  1351. wxT("Paint Brush"),
  1352. wxT("Pencil"),
  1353. wxT("Point Left"),
  1354. wxT("Point Right"),
  1355. wxT("Question Arrow"),
  1356. wxT("Right Button"),
  1357. wxT("Sizing NE-SW"),
  1358. wxT("Sizing N-S"),
  1359. wxT("Sizing NW-SE"),
  1360. wxT("Sizing W-E"),
  1361. wxT("Sizing"),
  1362. wxT("Spraycan"),
  1363. wxT("Wait"),
  1364. wxT("Watch"),
  1365. wxT("Wait Arrow"),
  1366. (const wxChar*) NULL
  1367. };
  1368. static const long gs_cp_es_syscursors_values[NUM_CURSORS] = {
  1369. wxCURSOR_NONE,
  1370. wxCURSOR_ARROW,
  1371. wxCURSOR_RIGHT_ARROW,
  1372. wxCURSOR_BLANK,
  1373. wxCURSOR_BULLSEYE,
  1374. wxCURSOR_CHAR,
  1375. wxCURSOR_CROSS,
  1376. wxCURSOR_HAND,
  1377. wxCURSOR_IBEAM,
  1378. wxCURSOR_LEFT_BUTTON,
  1379. wxCURSOR_MAGNIFIER,
  1380. wxCURSOR_MIDDLE_BUTTON,
  1381. wxCURSOR_NO_ENTRY,
  1382. wxCURSOR_PAINT_BRUSH,
  1383. wxCURSOR_PENCIL,
  1384. wxCURSOR_POINT_LEFT,
  1385. wxCURSOR_POINT_RIGHT,
  1386. wxCURSOR_QUESTION_ARROW,
  1387. wxCURSOR_RIGHT_BUTTON,
  1388. wxCURSOR_SIZENESW,
  1389. wxCURSOR_SIZENS,
  1390. wxCURSOR_SIZENWSE,
  1391. wxCURSOR_SIZEWE,
  1392. wxCURSOR_SIZING,
  1393. wxCURSOR_SPRAYCAN,
  1394. wxCURSOR_WAIT,
  1395. wxCURSOR_WATCH,
  1396. wxCURSOR_ARROWWAIT
  1397. };
  1398. IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty)
  1399. wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name,
  1400. int value )
  1401. : wxEnumProperty( label,
  1402. name,
  1403. gs_cp_es_syscursors_labels,
  1404. gs_cp_es_syscursors_values,
  1405. value )
  1406. {
  1407. m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
  1408. }
  1409. wxCursorProperty::~wxCursorProperty()
  1410. {
  1411. }
  1412. wxSize wxCursorProperty::OnMeasureImage( int item ) const
  1413. {
  1414. #if wxPG_CAN_DRAW_CURSOR
  1415. if ( item != -1 && item < NUM_CURSORS )
  1416. return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
  1417. #else
  1418. wxUnusedVar(item);
  1419. #endif
  1420. return wxSize(0,0);
  1421. }
  1422. #if wxPG_CAN_DRAW_CURSOR
  1423. void wxCursorProperty::OnCustomPaint( wxDC& dc,
  1424. const wxRect& rect,
  1425. wxPGPaintData& paintdata )
  1426. {
  1427. // Background brush
  1428. dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
  1429. if ( paintdata.m_choiceItem >= 0 )
  1430. {
  1431. dc.DrawRectangle( rect );
  1432. if ( paintdata.m_choiceItem < NUM_CURSORS )
  1433. {
  1434. wxStockCursor cursorIndex =
  1435. (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem];
  1436. {
  1437. if ( cursorIndex == wxCURSOR_NONE )
  1438. cursorIndex = wxCURSOR_ARROW;
  1439. wxCursor cursor( cursorIndex );
  1440. #ifdef __WXMSW__
  1441. HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC();
  1442. ::DrawIconEx( hDc,
  1443. rect.x,
  1444. rect.y,
  1445. (HICON)cursor.GetHandle(),
  1446. 0,
  1447. 0,
  1448. 0,
  1449. NULL,
  1450. #if !defined(__WXWINCE__)
  1451. DI_COMPAT | DI_DEFAULTSIZE |
  1452. #endif
  1453. DI_NORMAL
  1454. );
  1455. #endif
  1456. }
  1457. }
  1458. }
  1459. }
  1460. #else
  1461. void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
  1462. /*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
  1463. {
  1464. return wxEnumProperty::GetCellRenderer(column);
  1465. }*/
  1466. #endif
  1467. // -----------------------------------------------------------------------
  1468. // wxImageFileProperty
  1469. // -----------------------------------------------------------------------
  1470. #if wxUSE_IMAGE
  1471. const wxString& wxPGGetDefaultImageWildcard()
  1472. {
  1473. // Form the wildcard, if not done yet
  1474. if ( wxPGGlobalVars->m_pDefaultImageWildcard.empty() )
  1475. {
  1476. wxString str;
  1477. // TODO: This section may require locking (using global).
  1478. wxList& handlers = wxImage::GetHandlers();
  1479. wxList::iterator node;
  1480. // Let's iterate over the image handler list.
  1481. //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
  1482. for ( node = handlers.begin(); node != handlers.end(); ++node )
  1483. {
  1484. wxImageHandler *handler = (wxImageHandler*)*node;
  1485. wxString ext_lo = handler->GetExtension();
  1486. wxString ext_up = ext_lo.Upper();
  1487. str.append( ext_up );
  1488. str.append( wxT(" files (*.") );
  1489. str.append( ext_up );
  1490. str.append( wxT(")|*.") );
  1491. str.append( ext_lo );
  1492. str.append( wxT("|") );
  1493. }
  1494. str.append ( wxT("All files (*.*)|*.*") );