1 /*=========================================================================
3 Program: WXDialog - wxWidgets X-platform GUI Front-End for CMake
4 Module: $RCSfile: PropertyList.cpp,v $
6 Date: $Date: 2005/06/30 19:54:14 $
7 Version: $Revision: 1.1 $
11 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
12 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
14 This software is distributed WITHOUT ANY WARRANTY; without even
15 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 PURPOSE. See the above copyright notices for more information.
18 =========================================================================*/
20 /* for compilers that support precompilation
23 #include "wx/wxprec.h"
29 #include "PropertyList.h"
30 #include "app_resources.h"
32 #include "../cmCacheManager.h"
33 #include "../cmSystemTools.h"
36 BEGIN_EVENT_TABLE( wxPropertyList
, wxGrid
)
37 EVT_GRID_CELL_LEFT_CLICK( wxPropertyList::OnSelectCell
)
38 EVT_GRID_CELL_CHANGE( wxPropertyList::OnCellChange
)
39 EVT_GRID_CMD_CELL_RIGHT_CLICK( wxID_ANY
, wxPropertyList::OnCellPopup
)
40 EVT_MENU ( ID_CACHE_DELETE
, wxPropertyList::OnDeleteCache
)
41 EVT_MENU ( ID_CACHE_IGNORE
, wxPropertyList::OnIgnoreCache
)
42 EVT_MENU ( ID_CACHE_BROWSE
, wxPropertyList::OnBrowseItem
)
43 EVT_SIZE ( wxPropertyList::OnSizeGrid
)
44 EVT_CHAR ( wxPropertyList::OnKeyPressed
)
49 // ----------------------------------------------------------------------------
50 // wxGridCellPathEditor
51 // ----------------------------------------------------------------------------
53 wxGridCellPathEditor::wxGridCellPathEditor()
58 void wxGridCellPathEditor::Create(wxWindow
* parent
,
60 wxEvtHandler
* evtHandler
)
62 m_control
= new wxTextCtrl(parent
, id
, wxEmptyString
,
63 wxDefaultPosition
, wxDefaultSize
64 #if defined(__WXMSW__)
65 , wxTE_PROCESS_TAB
| wxTE_AUTO_SCROLL
69 // m_button = new wxButton(parent, id+1, _("..."),
70 // wxDefaultPosition, wxDefaultSize);
73 // set max length allowed in the textctrl, if the parameter was set
76 ((wxTextCtrl
*)m_control
)->SetMaxLength(m_maxChars
);
79 wxGridCellEditor::Create(parent
, id
, evtHandler
);
82 void wxGridCellPathEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
),
83 wxGridCellAttr
* WXUNUSED(attr
))
85 // as we fill the entire client area, don't do anything here to minimize
89 void wxGridCellPathEditor::SetSize(const wxRect
& rectOrig
)
91 wxRect
rect(rectOrig
);
93 // Make the edit control large enough to allow for internal
96 // TODO: remove this if the text ctrl sizing is improved esp. for
99 #if defined(__WXGTK__)
108 int extra_x
= ( rect
.x
> 2 )? 2 : 1;
110 // MB: treat MSW separately here otherwise the caret doesn't show
111 // when the editor is in the first row.
112 #if defined(__WXMSW__)
115 int extra_y
= ( rect
.y
> 2 )? 2 : 1;
118 #if defined(__WXMOTIF__)
122 rect
.SetLeft( wxMax(0, rect
.x
- extra_x
) );
123 rect
.SetTop( wxMax(0, rect
.y
- extra_y
) );
124 rect
.SetRight( rect
.GetRight() + 2*extra_x
);
125 rect
.SetBottom( rect
.GetBottom() + 2*extra_y
);
128 wxGridCellEditor::SetSize(rect
);
131 void wxGridCellPathEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
133 wxASSERT_MSG(m_control
,
134 wxT("The wxGridCellEditor must be Created first!"));
136 m_startValue
= grid
->GetTable()->GetValue(row
, col
);
138 DoBeginEdit(m_startValue
);
141 void wxGridCellPathEditor::DoBeginEdit(const wxString
& startValue
)
143 Text()->SetValue(startValue
);
144 Text()->SetInsertionPointEnd();
145 Text()->SetSelection(-1,-1);
149 bool wxGridCellPathEditor::EndEdit(int row
, int col
,
152 wxASSERT_MSG(m_control
,
153 wxT("The wxGridCellEditor must be Created first!"));
155 bool changed
= false;
156 wxString value
= Text()->GetValue();
157 if (value
!= m_startValue
)
161 grid
->GetTable()->SetValue(row
, col
, value
);
163 m_startValue
= wxEmptyString
;
164 // No point in setting the text of the hidden control
165 //Text()->SetValue(m_startValue);
171 void wxGridCellPathEditor::Reset()
173 wxASSERT_MSG(m_control
,
174 wxT("The wxGridCellEditor must be Created first!"));
176 DoReset(m_startValue
);
179 void wxGridCellPathEditor::DoReset(const wxString
& startValue
)
181 Text()->SetValue(startValue
);
182 Text()->SetInsertionPointEnd();
185 bool wxGridCellPathEditor::IsAcceptedKey(wxKeyEvent
& event
)
187 return wxGridCellEditor::IsAcceptedKey(event
);
190 void wxGridCellPathEditor::StartingKey(wxKeyEvent
& event
)
192 // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no
193 // longer an appropriate way to get the character into the text control.
194 // Do it ourselves instead. We know that if we get this far that we have
195 // a valid character, so not a whole lot of testing needs to be done.
197 wxTextCtrl
* tc
= Text();
202 ch
= event
.GetUnicodeKey();
204 ch
= (wxChar
)event
.GetKeyCode();
206 ch
= (wxChar
)event
.GetKeyCode();
211 // delete the character at the cursor
212 pos
= tc
->GetInsertionPoint();
213 if (pos
< tc
->GetLastPosition())
214 tc
->Remove(pos
, pos
+1);
218 // delete the character before the cursor
219 pos
= tc
->GetInsertionPoint();
221 tc
->Remove(pos
-1, pos
);
230 void wxGridCellPathEditor::HandleReturn( wxKeyEvent
&event
)
232 #if defined(__WXMOTIF__) || defined(__WXGTK__)
233 // wxMotif needs a little extra help...
234 size_t pos
= (size_t)( Text()->GetInsertionPoint() );
235 wxString
s( Text()->GetValue() );
236 s
= s
.Left(pos
) + wxT("\n") + s
.Mid(pos
);
238 Text()->SetInsertionPoint( pos
);
240 // the other ports can handle a Return key press
246 void wxGridCellPathEditor::SetParameters(const wxString
& params
)
256 if ( !params
.ToLong(&tmp
) )
258 wxLogDebug(_T("Invalid wxGridCellPathEditor parameter string '%s' ignored"), params
.c_str());
262 m_maxChars
= (size_t)tmp
;
267 // return the value in the text control
268 wxString
wxGridCellPathEditor::GetValue() const
270 return Text()->GetValue();
275 /////////////////////////////////////////////////////////////////////////////
278 // returns true when this property item is a filepath
279 bool wxPropertyItem::IsFilePath()
281 return m_nItemType
== wxPropertyList::FILE;
284 // returns true when this property item is a dir path
285 bool wxPropertyItem::IsDirPath()
287 return m_nItemType
== wxPropertyList::PATH
;
290 /////////////////////////////////////////////////////////////////////////////
293 wxPropertyList::~wxPropertyList()
295 WX_CLEAR_ARRAY(m_PropertyItems
);
298 int wxPropertyList::AddItem(const wxString
&txt
)
300 // TODO: Add the item to the grid!
302 //int nIndex = AddString(txt);
308 // order = 0 sorted (not supported yet)
309 // order = 1 add to top
310 // order = 2 add to bottom
311 int wxPropertyList::AddPropItem(wxPropertyItem
* pItem
, int order
)
313 m_PropertyItems
.Add(pItem
);
314 if(pItem
->GetAdvanced() && ! m_ShowAdvanced
)
317 // disable in progress editing
320 return AddPropertyToGrid(pItem
, order
);
323 int wxPropertyList::AddPropertyToGrid(wxPropertyItem
*pItem
, int order
)
331 row
= GetNumberRows() - 1;
334 // initialise the type of renderer
335 if(pItem
->GetItemType() == wxPropertyList::CHECKBOX
)
337 SetCellRenderer(row
, 1, new wxGridCellBoolRenderer
);
338 SetCellEditor(row
, 1, new wxGridCellBoolEditor
);
342 // fix to make sure scrollbars are drawn properly
343 wxGrid::AdjustScrollbars();
346 // the property display is read only
347 UpdatePropertyItem(pItem
, row
);
351 void wxPropertyList::AddProperty(const char* name
, const char* value
, const char* helpString
,
352 int type
, const char* comboItems
, bool reverseOrder
, bool advanced
)
354 wxPropertyItem
* pItem
= 0;
356 // add or update the property item
357 for(size_t i
= 0; i
< m_PropertyItems
.Count(); i
++)
359 if(m_PropertyItems
[i
]->GetPropName().IsSameAs(name
))
361 pItem
= m_PropertyItems
[i
];
362 if(!pItem
->GetCurValue().IsSameAs(value
))
364 pItem
->SetCurValue(value
);
365 pItem
->SetHelpString(helpString
);
366 pItem
->SetAdvanced(advanced
);
368 // update the property item
369 int row
= FindProperty(pItem
);
371 UpdatePropertyItem(pItem
, row
);
377 // if it is not found, then create a new one
380 pItem
= new wxPropertyItem(name
, value
, helpString
, type
, comboItems
);
381 pItem
->SetAdvanced(advanced
);
383 AddPropItem(pItem
, 1);
387 void wxPropertyList::UpdateGridView()
389 // make sure all items are shown, remove items that should not be shown
392 for(size_t i
= 0; i
< m_PropertyItems
.Count(); i
++)
394 // to begin with, does this item fit the query?
395 keepItem
= m_strQuery
.IsEmpty() || (m_PropertyItems
[i
]->GetPropName().Find(m_strQuery
) != -1);
398 // when advanced items are allowed to be shown, keep when ok
400 keepItem
= !m_PropertyItems
[i
]->GetAdvanced();
403 // find the item, if not present but keep is true, add, if
404 // present but keep is false, remove
406 for(size_t j
= 0; j
< (size_t)GetNumberRows(); j
++)
408 if(m_PropertyItems
[i
]->GetPropName().IsSameAs(GetCellValue(j
, 0)))
415 if(row
== -1 && keepItem
)
416 AddPropertyToGrid(m_PropertyItems
[i
], (m_ShowAdvanced
? 2 : 0));
417 else if(row
!= -1 && !keepItem
)
422 // fix to make sure scrollbars are drawn properly
423 wxGrid::AdjustScrollbars();
427 void wxPropertyList::HideControls()
429 DisableCellEditControl();
432 void wxPropertyList::RemoveProperty(wxPropertyItem
*pItem
)
436 // look for property in grid, delete it when present
437 for(size_t j
= 0; j
< (size_t)GetNumberRows(); j
++)
439 if(pItem
->GetPropName().IsSameAs(GetCellValue(j
, 0), false))
444 // fix to make sure scrollbars are drawn properly
445 wxGrid::AdjustScrollbars();
451 // delete the item from the list
452 m_PropertyItems
.Remove(pItem
);
456 wxPropertyItem
*wxPropertyList::FindPropertyByName(const wxString
&name
)
458 for(size_t i
= 0; i
< m_PropertyItems
.Count(); i
++)
460 // we have an advanced item, go through table and if not present, show it
461 if(m_PropertyItems
[i
]->GetPropName().IsSameAs(name
, true))
462 return m_PropertyItems
[i
];
469 void wxPropertyList::OnIgnore()
471 if(m_curSel == -1 || this->GetCount() <= 0)
475 wxPropertyItem* pItem = (wxPropertyItem*) GetItemDataPtr(m_curSel);
476 pItem->m_curValue = "IGNORE";
482 void wxPropertyList::OnDelete()
484 if(m_curSel == -1 || this->GetCount() <= 0)
488 wxPropertyItem* pItem = (wxPropertyItem*) GetItemDataPtr(m_curSel);
489 m_CMakeSetupDialog->GetCMakeInstance()->GetCacheManager()->RemoveCacheEntry(pItem->m_propName);
490 m_PropertyItems.erase(pItem);
492 this->DeleteString(m_curSel);
493 this->HideControls();
494 this->SetTopIndex(0);
500 void wxPropertyList::OnHelp()
502 if(m_curSel == -1 || this->GetCount() <= 0)
506 wxPropertyItem* pItem = (wxPropertyItem*) GetItemDataPtr(m_curSel);
507 MessageBox(pItem->m_HelpString, pItem->m_propName, MB_OK|MB_ICONINFORMATION);
511 void wxPropertyList::RemoveAll()
513 WX_CLEAR_ARRAY(m_PropertyItems
);
514 m_generatedProjects
= false;
516 if(GetNumberRows() > 0)
517 DeleteRows(0, GetNumberRows());
522 // fix to make sure scrollbars are drawn properly
523 wxGrid::AdjustScrollbars();
527 void wxPropertyList::ShowAdvanced()
529 // set flag in the control
530 m_ShowAdvanced
= true;
535 void wxPropertyList::HideAdvanced()
537 // set flag in the control
538 m_ShowAdvanced
= false;
542 int wxPropertyList::FindProperty(wxPropertyItem
*pItem
)
544 if(GetNumberRows() > 0 && pItem
!= 0)
546 // find the property the traditional way
547 for(size_t j
= 0; j
< (size_t)GetNumberRows(); j
++)
549 if(pItem
->GetPropName().IsSameAs(GetCellValue(j
, 0)))
557 wxPropertyItem
*wxPropertyList::GetPropertyItemFromRow(int row
)
559 if(row
< GetNumberRows() && row
>= 0)
561 wxString str
= GetCellValue(row
, 0);
562 // find the property the traditional way
563 for(size_t i
= 0; i
< (size_t)m_PropertyItems
.Count(); i
++)
565 if(m_PropertyItems
[i
]->GetPropName().IsSameAs(str
))
566 return m_PropertyItems
[i
];
573 bool wxPropertyList::UpdatePropertyItem(wxPropertyItem
*pItem
, int row
)
575 wxCHECK(row
< GetNumberRows(), false);
577 // reflect the property's state to match the grid row
580 // TODO: Make this a UpdatePropItem where ADVANCED, and new edit values are reflected
581 SetCellValue(row
,0, pItem
->GetPropName());
584 if(pItem
->GetItemType() == wxPropertyList::CHECKBOX
)
586 // translate ON or TRUE (case insensitive to a checkbox)
587 if(pItem
->GetCurValue().IsSameAs(wxT("ON"), false) ||
588 pItem
->GetCurValue().IsSameAs(wxT("TRUE"), false))
589 SetCellValue(row
, 1, wxT("1"));
591 SetCellValue(row
, 1, wxT("0"));
595 // for normal path values, give bold in cell when
596 // the NOTFOUND is present, for emphasis
597 wxString str
= pItem
->GetPropName() + wxT("-NOTFOUND");
598 if(pItem
->GetCurValue().IsSameAs(str
))
600 wxFont fnt
= GetCellFont(row
, 0);
601 fnt
.SetWeight(wxFONTWEIGHT_BOLD
);
602 SetCellFont(row
, 1, fnt
);
605 SetCellFont(row
, 1, GetCellFont(row
, 0));
607 SetCellValue(row
,1, pItem
->GetCurValue());
610 if(pItem
->GetCurValue().IsSameAs("IGNORE"))
612 // ignored cell is completely dimmed
613 wxColour
col(192,192,192);
614 SetCellTextColour(row
, 1, col
);
618 // we colour paths blue, filenames green, all else black
620 if(pItem
->IsDirPath())
622 else if(pItem
->IsFilePath())
625 col
= GetCellTextColour(row
, 0);
627 SetCellTextColour(row
, 1, col
);
630 if(pItem
->GetNewValue())
633 wxColour
col(255,100,100);
634 SetCellBackgroundColour(row
, 0, col
);
639 wxColour
col(192, 192, 192);
640 SetCellBackgroundColour(row
, 0, col
);
646 void wxPropertyList::OnSelectCell( wxGridEvent
& event
)
652 void wxPropertyList::OnCellChange( wxGridEvent
& event
)
654 int row
= event
.GetRow();
656 wxPropertyItem
*pItem
= GetPropertyItemFromRow(row
);
657 if(pItem
&& row
!= wxNOT_FOUND
)
659 // write propery back, and set as new
660 pItem
->SetNewValue(true);
663 if(pItem
->GetItemType() == CHECKBOX
)
665 if(GetCellValue(row
, 1).IsSameAs("1"))
666 pItem
->SetCurValue("ON");
668 pItem
->SetCurValue("OFF");
671 pItem
->SetCurValue(GetCellValue(row
, 1));
673 UpdatePropertyItem(pItem
, row
);
678 void wxPropertyList::OnCellPopup( wxGridEvent
& event
)
681 int row
= event
.GetRow();
683 //pt = ::wxGetMousePosition();
684 //ScreenToClient(pt);
686 //row = YToRow(pt.y);
687 if(row
!= wxNOT_FOUND
)
689 wxPropertyItem
*pItem
= GetPropertyItemFromRow(row
);
693 // select the row first if already in selection, don't
694 // this will clear the previous selection
695 if(!IsInSelection(row
, 0))
699 wxMenu
*menu
= AppResources::CreatePopupMenu();
701 // enable when it is browsable, and selected one only
702 wxMenuItem
*item
= menu
->FindItem(ID_CACHE_BROWSE
);
704 item
->Enable(IsSelectedItemBrowsable());
713 void wxPropertyList::OnIgnoreCache( wxCommandEvent
& event
)
717 // ignore all selected items
718 for(size_t i
= 0; i
< (size_t)GetNumberRows(); i
++)
720 if(IsInSelection(i
, 0))
722 wxPropertyItem
*pItem
= GetPropertyItemFromRow(i
);
725 pItem
->SetCurValue("IGNORE");
726 UpdatePropertyItem(pItem
, i
);
732 void wxPropertyList::OnDeleteCache( wxCommandEvent
& event
)
736 // convert selections to prop items
737 wxArrayPtrVoid items
;
738 for(size_t i
= 0; i
< (size_t)GetNumberRows(); i
++)
740 // if selected, query for removal
741 if(IsInSelection(i
, 0))
743 wxPropertyItem
*pItem
= GetPropertyItemFromRow(i
);
745 items
.Add((void *)pItem
);
749 // now delete all prop items in cells
750 for(size_t i
= 0; i
< items
.Count(); i
++)
751 RemoveProperty((wxPropertyItem
*)items
[i
]);
754 void wxPropertyList::OnBrowseItem( wxCommandEvent
& event
)
756 BrowseSelectedItem();
759 bool wxPropertyList::IsSelectedItemBrowsable(int row
)
761 // when there is only one selection, and our current item
762 // is browsable, make sure it can be selected.
763 wxPropertyItem
*pItem
= 0;
766 for(size_t i
= 0; i
< (size_t)GetNumberRows() && (count
< 2); i
++)
768 if(IsInSelection(i
, 0))
771 pItem
= GetPropertyItemFromRow(i
);
776 // if we found nothing, take row (because the event EVT_GRID_CELL_SELECTED
777 // deselects the cells first before selecting the new one again
778 if(row
!= -1 && !pItem
)
780 pItem
= GetPropertyItemFromRow(row
);
781 count
++; // needed because of next loop
784 // only one item allowed to select
785 if(pItem
&& count
== 1)
788 return pItem
->IsDirPath() || pItem
->IsFilePath();
795 void wxPropertyList::BrowseSelectedItem()
799 for(size_t i
= 0; i
< (size_t)GetNumberRows(); i
++)
801 if(IsInSelection(i
, 0))
803 // browse for file or directory
804 wxPropertyItem
*pItem
= GetPropertyItemFromRow(i
);
808 wxString str
= pItem
->GetPropName() + _("-NOTFOUND");
809 if(pItem
->GetCurValue().IsSameAs(str
, true))
812 str
= pItem
->GetCurValue();
814 // browse the directory path
816 if(pItem
->IsDirPath())
818 title
= _("Select path for ") + pItem
->GetPropName();
819 str
= ::wxDirSelector(title
, str
, 0, wxDefaultPosition
, this);
821 else if(pItem
->IsFilePath())
823 title
= _("Select file for ") + pItem
->GetPropName();
824 str
= ::wxFileSelector(title
, str
, _(""), _(""), _(MC_DEFAULT_WILDCARD
), wxFILE_MUST_EXIST
, this);
831 pItem
->SetCurValue(str
.c_str());
832 UpdatePropertyItem(pItem
, i
);
836 // only allow one item to browse
842 void wxPropertyList::OnSizeGrid( wxSizeEvent
&event
)
846 // make sure the grid's cells are equally adjusted
847 GetClientSize(&width
, &height
);
848 SetDefaultColSize(width
/ 2, true);
850 wxGrid::AdjustScrollbars();
853 void wxPropertyList::OnKeyPressed( wxKeyEvent
&event
)