1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
6 // This program is part of the eCos host tools.
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 // ----------------------------------------------------------------------------
24 //####COPYRIGHTEND####
27 //===========================================================================
28 //#####DESCRIPTIONBEGIN####
31 // Contact(s): julians
33 // Version: $Id: conflictsdlg.cpp,v 1.4 2001/07/09 14:21:32 julians Exp $
35 // Description: Implementation file for the ecResolveConflictsDialog
42 //####DESCRIPTIONEND####
44 //===========================================================================
46 // ============================================================================
48 // ============================================================================
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 #pragma implementation "conflictsdlg.h"
57 // Includes other headers for precompiled compilation
64 #include "configtool.h"
65 #include "conflictsdlg.h"
66 #include "conflictwin.h"
67 #include "solutionswin.h"
68 #include "configtooldoc.h"
69 #include "configtoolview.h"
70 #include "configtree.h"
72 #include "wx/cshelp.h"
74 BEGIN_EVENT_TABLE(ecResolveConflictsDialog, ecDialog)
75 EVT_BUTTON(ecID_CONFLICTS_ALL, ecResolveConflictsDialog::OnAll)
76 EVT_BUTTON(ecID_CONFLICTS_NONE, ecResolveConflictsDialog::OnNone)
77 EVT_BUTTON(ecID_CONFLICTS_CONTINUE, ecResolveConflictsDialog::OnContinue)
78 EVT_UPDATE_UI(ecID_CONFLICTS_ALL, ecResolveConflictsDialog::OnUpdateAll)
79 EVT_UPDATE_UI(ecID_CONFLICTS_NONE, ecResolveConflictsDialog::OnUpdateNone)
80 EVT_LIST_ITEM_SELECTED(ecID_CONFLICTS_CONFLICTS, ecResolveConflictsDialog::OnConflictSelected)
81 EVT_LIST_ITEM_DESELECTED(ecID_CONFLICTS_CONFLICTS, ecResolveConflictsDialog::OnConflictDeselected)
82 EVT_INIT_DIALOG(ecResolveConflictsDialog::OnInitDialog)
85 // ----------------------------------------------------------------------------
87 // ----------------------------------------------------------------------------
90 ecResolveConflictsDialog::ecResolveConflictsDialog(wxWindow* parent, std::list<CdlConflict> conflicts, CdlTransaction transaction, wxList *parConflictsOfInterest):
91 m_conflicts(conflicts),
92 m_Transaction(transaction),
93 m_parConflictsOfInterest(parConflictsOfInterest),
97 // Stop values from being changed by other mechanisms during the
98 // duration of this dialog.
99 wxGetApp().LockValues();
101 m_conflictsCtrl = NULL;
102 m_solutionsCtrl = NULL;
104 SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
106 ecDialog::Create(parent, ecID_RESOLVE_CONFLICTS_DIALOG, _("Resolve conflicts"),
107 wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
109 std::list<CdlConflict>::const_iterator conf_i;
110 for (conf_i= m_conflicts.begin (); conf_i != m_conflicts.end (); conf_i++)
111 { // for each conflict
112 int nSolutions = (*conf_i)->get_solution().size();
113 SolutionInfo *pInfo = (SolutionInfo *) malloc(sizeof(SolutionInfo)+(nSolutions-1)*sizeof(int));
114 pInfo->nCount = nSolutions;
116 for ( i = 0; i < nSolutions; i++)
118 pInfo->arItem[i] = SolutionInfo::CHECKED;
120 m_Map.Put((long) *conf_i, (wxObject*) pInfo);
123 CreateControls(this);
128 ecResolveConflictsDialog::~ecResolveConflictsDialog()
132 while ((node = m_Map.Next()))
134 SolutionInfo *pInfo = (SolutionInfo*) node->Data();
139 // OK to change values again
140 wxGetApp().UnlockValues();
143 void ecResolveConflictsDialog::CreateControls(wxWindow* parent)
145 // Create custom windows first
146 m_conflictsCtrl = new ecConflictListCtrl(parent, ecID_CONFLICTS_CONFLICTS, wxDefaultPosition, wxSize(470, 110), wxLC_REPORT|wxCLIP_CHILDREN|wxSUNKEN_BORDER);
147 m_solutionsCtrl = new ecSolutionListCtrl(parent, ecID_CONFLICTS_SOLUTIONS, wxDefaultPosition, wxSize(470, 110), wxLC_REPORT|wxCLIP_CHILDREN|wxSUNKEN_BORDER);
149 wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
151 wxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
153 wxButton *item2 = new wxButton( parent, ecID_CONFLICTS_CONTINUE, _("&Continue"), wxDefaultPosition, wxDefaultSize, 0 );
155 item1->Add( item2, 0, wxALIGN_CENTRE|wxALL, 5 );
157 wxButton *item3 = new wxButton( parent, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
158 item1->Add( item3, 0, wxALIGN_CENTRE|wxALL, 5 );
160 item0->Add( item1, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
162 wxWindow *item4 = parent->FindWindow( ecID_CONFLICTS_CONFLICTS );
164 item0->Add( item4, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
166 wxSizer *item5 = new wxBoxSizer( wxHORIZONTAL );
168 wxStaticText *item6 = new wxStaticText( parent, ecID_CONFLICTS_MSG, _("Proposed Solutions:"), wxDefaultPosition, wxSize(250,-1), 0 );
169 item5->Add( item6, 0, wxALIGN_BOTTOM|wxALIGN_CENTER_HORIZONTAL|wxALL, 0 );
171 item5->Add( 30, 20, 1, wxALIGN_CENTRE|wxALL, 0 );
173 wxButton *item7 = new wxButton( parent, ecID_CONFLICTS_NONE, _("&None"), wxDefaultPosition, wxDefaultSize, 0 );
174 item5->Add( item7, 0, wxALIGN_CENTRE|wxALL, 5 );
176 wxButton *item8 = new wxButton( parent, ecID_CONFLICTS_ALL, _("&All"), wxDefaultPosition, wxDefaultSize, 0 );
177 item5->Add( item8, 0, wxALIGN_CENTRE|wxALL, 5 );
179 item0->Add( item5, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
181 wxWindow *item9 = parent->FindWindow( ecID_CONFLICTS_SOLUTIONS );
183 item0->Add( item9, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
186 wxButton *contextButton = new wxContextHelpButton( parent );
187 item1->Add( contextButton, 0, wxALIGN_CENTRE|wxALL, 5 );
190 parent->SetAutoLayout( TRUE );
191 parent->SetSizer( item0 );
193 // N.B. I find I have to call Layout, then Fit, to make this
196 item0->Fit( parent );
197 item0->SetSizeHints( parent );
199 // Add context-sensitive help text
200 parent->FindWindow( ecID_CONFLICTS_CONFLICTS )->SetHelpText(_("Displays the set of conflicts for which the fixes are offered."));
201 parent->FindWindow( ecID_CONFLICTS_SOLUTIONS )->SetHelpText(_("Displays fixes for the currently selected conflict. Use the checkboxes to enable or disable each fix."));
202 parent->FindWindow( ecID_CONFLICTS_CONTINUE )->SetHelpText(_("Continues the current transaction, applying the selected solutions."));
203 parent->FindWindow( wxID_CANCEL )->SetHelpText(_("Cancels the current transaction, without applying any solutions."));
204 parent->FindWindow( ecID_CONFLICTS_NONE )->SetHelpText(_("Resets all fix checkboxes to the unchecked state."));
205 parent->FindWindow( ecID_CONFLICTS_ALL )->SetHelpText(_("Resets all fix checkboxes to the checked state."));
208 parent->FindWindow( wxID_CONTEXT_HELP )->SetHelpText(_("Invokes context-sensitive help for the clicked-on window."));
212 void ecResolveConflictsDialog::OnInitDialog(wxInitDialogEvent& event)
214 wxDialog::OnInitDialog(event);
216 // Select the first item and fill the solution set
217 m_conflictsCtrl->AddConflicts(m_conflicts);
219 if (m_parConflictsOfInterest && m_parConflictsOfInterest->Number()>0)
221 wxList &arConflictsOfInterest = *m_parConflictsOfInterest;
223 for ( i = m_conflictsCtrl->GetItemCount() - 1; i >= 0; --i )
225 for ( j = arConflictsOfInterest.Number() - 1; j>=0; --j )
227 CdlConflict conflict = (CdlConflict)m_conflictsCtrl->GetItemData(i);
228 if ( ((CdlConflict) arConflictsOfInterest[j]) == conflict )
230 m_conflictsCtrl->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
231 m_conflictsCtrl->EnsureVisible(i);
232 arConflictsOfInterest.DeleteObject(arConflictsOfInterest[j]);
239 for ( int i = m_conflictsCtrl->GetItemCount()-1; i>=0; --i )
241 m_conflictsCtrl->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
244 m_conflictsCtrl->SetFocus();
247 void ecResolveConflictsDialog::OnContinue(wxCommandEvent& event)
249 // Ensure we have the current conflict check array
251 for (i = 0; i < m_conflictsCtrl->GetItemCount(); i++)
253 if (m_conflictsCtrl->GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
254 RemoveConflictSolutions((CdlConflict) m_conflictsCtrl->GetItemData(i));
257 // Dismiss the window
260 std::list<CdlConflict>::const_iterator conf_i;
262 for (conf_i= m_conflicts.begin (); conf_i != m_conflicts.end (); conf_i++) // for each conflict
264 CdlConflict conflict=*conf_i;
265 //int nSolutions=conflict->get_solution().size();
266 SolutionInfo &info=Info(conflict);
268 const std::vector<std::pair<CdlValuable, CdlValue> >&Solution=conflict->get_solution();
269 for (std::vector<std::pair<CdlValuable, CdlValue> >::const_iterator soln_i = Solution.begin();soln_i != Solution.end(); soln_i++) {
270 if(SolutionInfo::CHECKED==info.arItem[nIndex++]){
271 CdlValuable valuable = soln_i->first;
272 CdlValue value=soln_i->second;
273 CdlValueFlavor flavor = valuable->get_flavor();
274 const wxString strName(valuable->get_name().c_str());
275 const wxString strValue(value.get_value().c_str());
282 case CdlValueFlavor_None :
283 str = wxT("set CdlValueFlavor_None");
286 case CdlValueFlavor_Bool :
287 str.Printf(_("%s %s\n"), (const wxChar*) (value.is_enabled()?_("disable"):_("enable")), (const wxChar*) strName);
288 valuable->set_enabled (m_Transaction, value.is_enabled(), CdlValueSource_User);
290 case CdlValueFlavor_BoolData :
292 bool bEnabled=value.is_enabled();
293 str.Printf(_("%s %s and set value to %s\n"), (const wxChar*) (bEnabled? _("disable"):_("enable")), (const wxChar*) strName, (const wxChar*) strValue);
294 // Surely this is wrong - we don't want to set the same value, we want to
296 // CdlSimpleValue simple_value = valuable->get_simple_value ();
297 //valuable->set_enabled_and_value (m_Transaction, bEnabled, simple_value, CdlValueSource_User);
298 valuable->set_enabled_and_value (m_Transaction, bEnabled, ecUtils::UnicodeToStdStr (strValue), CdlValueSource_User);
301 case CdlValueFlavor_Data :
302 str.Printf(_("set %s to %s\n"), (const wxChar*) strName, (const wxChar*) strValue);
303 valuable->set_value (m_Transaction, ecUtils::UnicodeToStdStr (strValue), CdlValueSource_User);
313 wxGetApp().GetConfigToolDoc()->Modify(TRUE);
317 msg.Printf(_("Failed to %s\n"), (const wxChar*) str);
318 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
325 void ecResolveConflictsDialog::OnAll(wxCommandEvent& event)
330 void ecResolveConflictsDialog::OnNone(wxCommandEvent& event)
335 void ecResolveConflictsDialog::SetAll(bool bOnOff)
338 for ( i = m_solutionsCtrl->GetItemCount()-1; i >= 0; --i)
340 m_solutionsCtrl->SetChecked(i, bOnOff);
345 void ecResolveConflictsDialog::OnUpdateAll(wxUpdateUIEvent& event)
347 if (!m_solutionsCtrl)
351 int nItemCount = m_solutionsCtrl->GetItemCount();
353 for (i=nItemCount-1;i>=0;--i)
355 nCheckCount+=m_solutionsCtrl->IsChecked(i);
357 event.Enable(nItemCount>0 && nCheckCount<nItemCount);
360 // Update None button
361 void ecResolveConflictsDialog::OnUpdateNone(wxUpdateUIEvent& event)
363 if (!m_solutionsCtrl)
367 int nItemCount=m_solutionsCtrl->GetItemCount();
369 for (i=nItemCount-1;i>=0;--i){
370 nCheckCount+=m_solutionsCtrl->IsChecked(i);
372 event.Enable(nItemCount>0 && nCheckCount>0);
375 // Currently there is no 'locate' button so this is not called from anywhere.
376 // However, the intention in the MFC configtool must have been to use it,
377 // although it wasn't in the Resolve Conflicts dialog.
378 void ecResolveConflictsDialog::OnLocate()
380 ecConfigItem *pItem = m_conflictsCtrl->AssociatedItem(m_nContextItem, m_nContextRow);
382 if (wxGetApp().GetTreeCtrl())
383 wxGetApp().GetTreeCtrl()->SelectItem(pItem->GetTreeItem());
387 void ecResolveConflictsDialog::RemoveConflictSolutions(CdlConflict conflict)
389 SolutionInfo &info=Info(conflict);
391 for ( i = 0; i < info.nCount; i++ )
393 int nItem=info.arItem[i];
395 info.arItem[i] = (m_solutionsCtrl->IsChecked(nItem) ? SolutionInfo::CHECKED:SolutionInfo::UNCHECKED);
396 int nRefs = m_solutionsCtrl->GetItemData(nItem);
399 m_solutionsCtrl->DeleteItem(nItem);
400 for ( k = 0; k < m_conflictsCtrl->GetItemCount(); k++ )
402 SolutionInfo &info2 = Info((CdlConflict)m_conflictsCtrl->GetItemData(k));
403 for ( j = 0; j < info2.nCount; j++)
405 if (info2.arItem[j] > nItem)
413 m_solutionsCtrl->SetItemData(nItem, nRefs-1);
418 void ecResolveConflictsDialog::AddConflictSolutions(CdlConflict conflict)
420 // SolutionInfo allows each conflict to know which solutions have been found for it
421 SolutionInfo &info=Info(conflict);
423 const std::vector<std::pair<CdlValuable, CdlValue> >&Solution=conflict->get_solution();
426 for (std::vector<std::pair<CdlValuable, CdlValue> >::const_iterator soln_i = Solution.begin();
427 soln_i != Solution.end(); soln_i++)
429 CdlValuable valuable = soln_i->first;
430 CdlValue value = soln_i->second;
431 CdlValueFlavor flavor = valuable->get_flavor();
436 case CdlValueFlavor_None :
438 case CdlValueFlavor_Bool :
439 strValue = value.is_enabled() ? _("Enabled") : _("Disabled");
441 case CdlValueFlavor_BoolData :
442 strValue.Printf(wxT("%s, %s"), (const wxChar*) (value.is_enabled() ? _("Enabled") : _("Disabled")), (const wxChar*) value.get_value().c_str());
444 case CdlValueFlavor_Data :
445 strValue = value.get_value().c_str();
449 const wxString strName(soln_i->first->get_name().c_str());
451 long nIndex = m_solutionsCtrl->FindItem(0, strName);
453 listItem.m_mask = wxLIST_MASK_TEXT;
454 listItem.m_itemId = nIndex;
457 m_solutionsCtrl->GetItem(listItem);
459 if (-1 == nIndex || strValue != listItem.m_text)
461 // We don't have an existing solution that matches this one
462 nIndex = m_solutionsCtrl->GetItemCount();
463 m_solutionsCtrl->InsertItem(nIndex, strName);
464 m_solutionsCtrl->SetItemData(nIndex, 1);
465 m_solutionsCtrl->SetItem(nIndex, 1, strValue);
467 wxASSERT(info.arItem[i]<0);
469 m_solutionsCtrl->SetChecked(nIndex, SolutionInfo::CHECKED==info.arItem[i]);
471 // We do - to avoid duplicates, increment the "ref count"
472 m_solutionsCtrl->SetItemData(nIndex, m_solutionsCtrl->GetItemData(nIndex)+1);
474 info.arItem[i++]=nIndex;
477 wxStaticText* staticCtrl = (wxStaticText*) FindWindow(ecID_CONFLICTS_MSG);
480 staticCtrl->SetLabel(_("No solution is available for this conflict"));
481 m_solutionsCtrl->Show(FALSE);
483 staticCtrl->SetLabel(_("Proposed solution:"));
484 m_solutionsCtrl->Show(TRUE);
485 // TODO (if necessary)
487 m_List.SetColumnWidth(0,LVSCW_AUTOSIZE);
489 m_List.GetClientRect(rect);
490 m_List.SetColumnWidth(1,rect.Width()-m_List.GetColumnWidth(0));
495 ecResolveConflictsDialog::SolutionInfo & ecResolveConflictsDialog::Info(const CdlConflict conflict)
497 SolutionInfo *pInfo = (SolutionInfo*) m_Map.Get((long) conflict);
501 void ecResolveConflictsDialog::OnConflictSelected(wxListEvent& event)
503 CdlConflict conflict=(CdlConflict) m_conflictsCtrl->GetItemData(event.GetIndex());
505 if (1 == m_solutionsCtrl->GetSelectedItemCount())
508 // GetDlgItem(IDC_STATIC1)->ShowWindow(SW_HIDE);
509 m_solutionsCtrl->Show(TRUE);
511 AddConflictSolutions(conflict);
514 void ecResolveConflictsDialog::OnConflictDeselected(wxListEvent& event)
516 CdlConflict conflict=(CdlConflict) m_conflictsCtrl->GetItemData(event.GetIndex());
518 RemoveConflictSolutions(conflict);
525 // We need to use this because the OnItemChanged handler successive receives "not selected" followed by "selected"
526 // notifications. The result is that the "Select one or more conflicts to display available solutions" message
527 // would be seen briefly when clicking from one selection to another.
528 BOOL ecResolveConflictsDialog::OnClick(UINT,LPNMLISTVIEW pnmv, LRESULT* pResult)
530 if(-1==pnmv->iItem && 0==m_List.GetSelectedCount()){
531 SetDlgItemText(IDC_STATIC1,_T("Select one or more conflicts to display available solutions"));
532 m_List.ShowWindow(SW_HIDE);
533 GetDlgItem(IDC_STATIC1)->ShowWindow(SW_SHOW);
534 GetDlgItem(IDC_RESET)->EnableWindow(false);
535 GetDlgItem(IDC_CONFLICTS_NONE)->EnableWindow(false);
538 return false; // not handled
542 BOOL ecResolveConflictsDialog::OnRClick(UINT, LPNMITEMACTIVATE pnmv, LRESULT* pResult)
544 DWORD dwPos=GetMessagePos();
545 CPoint pt(GET_X_LPARAM(dwPos),GET_Y_LPARAM(dwPos));
546 m_nContextItem=pnmv->iItem;
547 m_nContextRow=pnmv->iSubItem;
548 if(-1!=m_nContextItem){
549 //m_RulesList.SetItemState(m_nContextItem,LVIS_SELECTED,LVIS_SELECTED);
551 menu.CreatePopupMenu();
552 menu.AppendMenu(1==m_RulesList.GetSelectedCount() && m_RulesList.AssociatedItem(m_nContextItem,m_nContextRow)?MF_STRING:(MF_STRING|MF_GRAYED),ID_LOCATE,_T("&Locate"));
554 SuppressNextContextMenuMessage();
556 menu.TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, pt.x,pt.y,this);
560 return TRUE; // handled