Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / WXDialog / PropertyList.cpp
blob8bbf2a2afd6358dc18ec7ff2b8a13cd80f3f058d
1 /*=========================================================================
3 Program: WXDialog - wxWidgets X-platform GUI Front-End for CMake
4 Module: $RCSfile: PropertyList.cpp,v $
5 Language: C++
6 Date: $Date: 2005/06/30 19:54:14 $
7 Version: $Revision: 1.1 $
9 Author: Jorgen Bodde
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
21 includes "wx/wx.h" */
23 #include "wx/wxprec.h"
25 #ifdef __BORLANDC__
26 #pragma hdrstop
27 #endif
29 #include "PropertyList.h"
30 #include "app_resources.h"
32 #include "../cmCacheManager.h"
33 #include "../cmSystemTools.h"
34 #include "../cmake.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 )
45 END_EVENT_TABLE()
47 #if 0
49 // ----------------------------------------------------------------------------
50 // wxGridCellPathEditor
51 // ----------------------------------------------------------------------------
53 wxGridCellPathEditor::wxGridCellPathEditor()
55 m_maxChars = 0;
58 void wxGridCellPathEditor::Create(wxWindow* parent,
59 wxWindowID id,
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
66 #endif
69 // m_button = new wxButton(parent, id+1, _("..."),
70 // wxDefaultPosition, wxDefaultSize);
73 // set max length allowed in the textctrl, if the parameter was set
74 if (m_maxChars != 0)
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
86 // flicker
89 void wxGridCellPathEditor::SetSize(const wxRect& rectOrig)
91 wxRect rect(rectOrig);
93 // Make the edit control large enough to allow for internal
94 // margins
96 // TODO: remove this if the text ctrl sizing is improved esp. for
97 // unix
99 #if defined(__WXGTK__)
100 if (rect.x != 0)
102 rect.x += 1;
103 rect.y += 1;
104 rect.width -= 1;
105 rect.height -= 1;
107 #else // !GTK
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__)
113 int extra_y = 2;
114 #else
115 int extra_y = ( rect.y > 2 )? 2 : 1;
116 #endif // MSW
118 #if defined(__WXMOTIF__)
119 extra_x *= 2;
120 extra_y *= 2;
121 #endif
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 );
126 #endif // GTK/!GTK
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);
146 Text()->SetFocus();
149 bool wxGridCellPathEditor::EndEdit(int row, int col,
150 wxGrid* grid)
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)
158 changed = true;
160 if (changed)
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);
167 return changed;
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();
198 wxChar ch;
199 long pos;
201 #if wxUSE_UNICODE
202 ch = event.GetUnicodeKey();
203 if (ch <= 127)
204 ch = (wxChar)event.GetKeyCode();
205 #else
206 ch = (wxChar)event.GetKeyCode();
207 #endif
208 switch (ch)
210 case WXK_DELETE:
211 // delete the character at the cursor
212 pos = tc->GetInsertionPoint();
213 if (pos < tc->GetLastPosition())
214 tc->Remove(pos, pos+1);
215 break;
217 case WXK_BACK:
218 // delete the character before the cursor
219 pos = tc->GetInsertionPoint();
220 if (pos > 0)
221 tc->Remove(pos-1, pos);
222 break;
224 default:
225 tc->WriteText(ch);
226 break;
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);
237 Text()->SetValue(s);
238 Text()->SetInsertionPoint( pos );
239 #else
240 // the other ports can handle a Return key press
242 event.Skip();
243 #endif
246 void wxGridCellPathEditor::SetParameters(const wxString& params)
248 if ( !params )
250 // reset to default
251 m_maxChars = 0;
253 else
255 long tmp;
256 if ( !params.ToLong(&tmp) )
258 wxLogDebug(_T("Invalid wxGridCellPathEditor parameter string '%s' ignored"), params.c_str());
260 else
262 m_maxChars = (size_t)tmp;
267 // return the value in the text control
268 wxString wxGridCellPathEditor::GetValue() const
270 return Text()->GetValue();
273 #endif
275 /////////////////////////////////////////////////////////////////////////////
276 // wxPropertyItem
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 /////////////////////////////////////////////////////////////////////////////
291 // wxPropertyList
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);
303 //return nIndex;
305 return 0;
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)
315 return 0;
317 // disable in progress editing
318 HideControls();
320 return AddPropertyToGrid(pItem, order);
323 int wxPropertyList::AddPropertyToGrid(wxPropertyItem *pItem, int order)
325 int row = 0;
326 if(order == 1)
327 InsertRows(0,1);
328 else
330 AppendRows(1);
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);
341 #ifdef __LINUX__
342 // fix to make sure scrollbars are drawn properly
343 wxGrid::AdjustScrollbars();
344 #endif
346 // the property display is read only
347 UpdatePropertyItem(pItem, row);
348 return 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);
370 if(row != -1)
371 UpdatePropertyItem(pItem, row);
373 return;
377 // if it is not found, then create a new one
378 if(!pItem)
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
390 bool keepItem;
391 int row;
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);
396 if(keepItem)
398 // when advanced items are allowed to be shown, keep when ok
399 if(!m_ShowAdvanced)
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
405 row = -1;
406 for(size_t j = 0; j < (size_t)GetNumberRows(); j++)
408 if(m_PropertyItems[i]->GetPropName().IsSameAs(GetCellValue(j, 0)))
410 row = j;
411 break;
415 if(row == -1 && keepItem)
416 AddPropertyToGrid(m_PropertyItems[i], (m_ShowAdvanced ? 2 : 0));
417 else if(row != -1 && !keepItem)
418 DeleteRows(row, 1);
421 #ifdef __LINUX__
422 // fix to make sure scrollbars are drawn properly
423 wxGrid::AdjustScrollbars();
424 #endif
427 void wxPropertyList::HideControls()
429 DisableCellEditControl();
432 void wxPropertyList::RemoveProperty(wxPropertyItem *pItem)
434 HideControls();
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))
441 DeleteRows(j, 1);
443 #ifdef __LINUX__
444 // fix to make sure scrollbars are drawn properly
445 wxGrid::AdjustScrollbars();
446 #endif
447 break;
451 // delete the item from the list
452 m_PropertyItems.Remove(pItem);
453 delete 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];
465 return 0;
469 void wxPropertyList::OnIgnore()
471 if(m_curSel == -1 || this->GetCount() <= 0)
473 return;
475 wxPropertyItem* pItem = (wxPropertyItem*) GetItemDataPtr(m_curSel);
476 pItem->m_curValue = "IGNORE";
477 InvalidateList();
482 void wxPropertyList::OnDelete()
484 if(m_curSel == -1 || this->GetCount() <= 0)
486 return;
488 wxPropertyItem* pItem = (wxPropertyItem*) GetItemDataPtr(m_curSel);
489 m_CMakeSetupDialog->GetCMakeInstance()->GetCacheManager()->RemoveCacheEntry(pItem->m_propName);
490 m_PropertyItems.erase(pItem);
491 delete pItem;
492 this->DeleteString(m_curSel);
493 this->HideControls();
494 this->SetTopIndex(0);
495 InvalidateList();
500 void wxPropertyList::OnHelp()
502 if(m_curSel == -1 || this->GetCount() <= 0)
504 return;
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());
519 m_strQuery.Empty();
521 #ifdef __LINUX__
522 // fix to make sure scrollbars are drawn properly
523 wxGrid::AdjustScrollbars();
524 #endif
527 void wxPropertyList::ShowAdvanced()
529 // set flag in the control
530 m_ShowAdvanced = true;
531 UpdateGridView();
535 void wxPropertyList::HideAdvanced()
537 // set flag in the control
538 m_ShowAdvanced = false;
539 UpdateGridView();
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)))
550 return j;
554 return -1;
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];
570 return 0;
573 bool wxPropertyList::UpdatePropertyItem(wxPropertyItem *pItem, int row)
575 wxCHECK(row < GetNumberRows(), false);
577 // reflect the property's state to match the grid row
579 SetReadOnly(row, 0);
580 // TODO: Make this a UpdatePropItem where ADVANCED, and new edit values are reflected
581 SetCellValue(row,0, pItem->GetPropName());
583 // boolean renderer
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"));
590 else
591 SetCellValue(row, 1, wxT("0"));
593 else
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);
604 else
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);
616 else
618 // we colour paths blue, filenames green, all else black
619 wxColour col;
620 if(pItem->IsDirPath())
621 col.Set(0,0,255);
622 else if(pItem->IsFilePath())
623 col.Set(0,128,0);
624 else
625 col = GetCellTextColour(row, 0);
627 SetCellTextColour(row, 1, col);
630 if(pItem->GetNewValue())
632 // new cell is red
633 wxColour col(255,100,100);
634 SetCellBackgroundColour(row, 0, col);
636 else
638 // old cell is grey
639 wxColour col(192, 192, 192);
640 SetCellBackgroundColour(row, 0, col);
643 return true;
646 void wxPropertyList::OnSelectCell( wxGridEvent& event )
648 this->SetFocus();
649 event.Skip();
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);
662 // write back bool
663 if(pItem->GetItemType() == CHECKBOX)
665 if(GetCellValue(row, 1).IsSameAs("1"))
666 pItem->SetCurValue("ON");
667 else
668 pItem->SetCurValue("OFF");
670 else
671 pItem->SetCurValue(GetCellValue(row, 1));
673 UpdatePropertyItem(pItem, row);
674 event.Skip();
678 void wxPropertyList::OnCellPopup( wxGridEvent& event )
680 wxPoint pt;
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);
691 if(pItem)
693 // select the row first if already in selection, don't
694 // this will clear the previous selection
695 if(!IsInSelection(row, 0))
696 SelectRow(row);
698 // show popup menu
699 wxMenu *menu = AppResources::CreatePopupMenu();
701 // enable when it is browsable, and selected one only
702 wxMenuItem *item = menu->FindItem(ID_CACHE_BROWSE);
703 if(item)
704 item->Enable(IsSelectedItemBrowsable());
706 PopupMenu(menu);
708 delete menu;
713 void wxPropertyList::OnIgnoreCache( wxCommandEvent& event )
715 HideControls();
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);
723 if(pItem)
725 pItem->SetCurValue("IGNORE");
726 UpdatePropertyItem(pItem, i);
732 void wxPropertyList::OnDeleteCache( wxCommandEvent& event )
734 HideControls();
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);
744 if(pItem)
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;
765 size_t count = 0;
766 for(size_t i = 0; i < (size_t)GetNumberRows() && (count < 2); i++)
768 if(IsInSelection(i, 0))
770 if(!pItem)
771 pItem = GetPropertyItemFromRow(i);
772 count ++;
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)
787 if(pItem)
788 return pItem->IsDirPath() || pItem->IsFilePath();
791 return false;
795 void wxPropertyList::BrowseSelectedItem()
797 HideControls();
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);
805 if(pItem)
807 wxString title;
808 wxString str = pItem->GetPropName() + _("-NOTFOUND");
809 if(pItem->GetCurValue().IsSameAs(str, true))
810 str.Empty();
811 else
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);
826 else
827 str.Empty();
829 if(!str.IsEmpty())
831 pItem->SetCurValue(str.c_str());
832 UpdatePropertyItem(pItem, i);
836 // only allow one item to browse
837 break;
842 void wxPropertyList::OnSizeGrid( wxSizeEvent &event )
844 int width, height;
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 )
855 event.Skip();