]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/wxwin/conflictsdlg.cpp
Cleanup CVS ipmorted branch
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / wxwin / conflictsdlg.cpp
1 //####COPYRIGHTBEGIN####
2 //
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
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)
11 // any later version.
12 //
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
16 // more details.
17 //
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.
21 //
22 // ----------------------------------------------------------------------------
23 //
24 //####COPYRIGHTEND####
25 // conflictsdlg.cpp :
26 //
27 //===========================================================================
28 //#####DESCRIPTIONBEGIN####
29 //
30 // Author(s):   julians
31 // Contact(s):  julians
32 // Date:        2000/09/06
33 // Version:     $Id: conflictsdlg.cpp,v 1.4 2001/07/09 14:21:32 julians Exp $
34 // Purpose:
35 // Description: Implementation file for the ecResolveConflictsDialog
36 // Requires:
37 // Provides:
38 // See also:
39 // Known bugs:
40 // Usage:
41 //
42 //####DESCRIPTIONEND####
43 //
44 //===========================================================================
45
46 // ============================================================================
47 // declarations
48 // ============================================================================
49
50 // ----------------------------------------------------------------------------
51 // headers
52 // ----------------------------------------------------------------------------
53 #ifdef __GNUG__
54 #pragma implementation "conflictsdlg.h"
55 #endif
56
57 // Includes other headers for precompiled compilation
58 #include "ecpch.h"
59
60 #ifdef __BORLANDC__
61 #pragma hdrstop
62 #endif
63
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"
71
72 #include "wx/cshelp.h"
73
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)
83 END_EVENT_TABLE()
84
85 // ----------------------------------------------------------------------------
86 // main frame
87 // ----------------------------------------------------------------------------
88
89 // Frame constructor
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),
94     m_Map(wxKEY_INTEGER)
95
96 {
97     // Stop values from being changed by other mechanisms during the
98     // duration of this dialog.
99     wxGetApp().LockValues();
100
101     m_conflictsCtrl = NULL;
102     m_solutionsCtrl = NULL;
103
104     SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
105
106     ecDialog::Create(parent, ecID_RESOLVE_CONFLICTS_DIALOG, _("Resolve conflicts"),
107         wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
108
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;
115         int i;
116         for ( i = 0; i < nSolutions; i++)
117         {
118             pInfo->arItem[i] = SolutionInfo::CHECKED;
119         }
120         m_Map.Put((long) *conf_i, (wxObject*) pInfo);
121     }
122
123     CreateControls(this);
124
125     Centre(wxBOTH);
126 }
127
128 ecResolveConflictsDialog::~ecResolveConflictsDialog()
129 {
130     m_Map.BeginFind();
131     wxNode* node = NULL;
132     while ((node = m_Map.Next()))
133     {
134         SolutionInfo *pInfo = (SolutionInfo*) node->Data();
135         free(pInfo);
136     }
137     m_Map.Clear();
138
139     // OK to change values again
140     wxGetApp().UnlockValues();
141 }
142
143 void ecResolveConflictsDialog::CreateControls(wxWindow* parent)
144 {
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);
148
149     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
150
151     wxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
152
153     wxButton *item2 = new wxButton( parent, ecID_CONFLICTS_CONTINUE, _("&Continue"), wxDefaultPosition, wxDefaultSize, 0 );
154     item2->SetDefault();
155     item1->Add( item2, 0, wxALIGN_CENTRE|wxALL, 5 );
156
157     wxButton *item3 = new wxButton( parent, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
158     item1->Add( item3, 0, wxALIGN_CENTRE|wxALL, 5 );
159
160     item0->Add( item1, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
161
162     wxWindow *item4 = parent->FindWindow( ecID_CONFLICTS_CONFLICTS );
163     wxASSERT( item4 );
164     item0->Add( item4, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
165
166     wxSizer *item5 = new wxBoxSizer( wxHORIZONTAL );
167
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 );
170
171     item5->Add( 30, 20, 1, wxALIGN_CENTRE|wxALL, 0 );
172
173     wxButton *item7 = new wxButton( parent, ecID_CONFLICTS_NONE, _("&None"), wxDefaultPosition, wxDefaultSize, 0 );
174     item5->Add( item7, 0, wxALIGN_CENTRE|wxALL, 5 );
175
176     wxButton *item8 = new wxButton( parent, ecID_CONFLICTS_ALL, _("&All"), wxDefaultPosition, wxDefaultSize, 0 );
177     item5->Add( item8, 0, wxALIGN_CENTRE|wxALL, 5 );
178
179     item0->Add( item5, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
180
181     wxWindow *item9 = parent->FindWindow( ecID_CONFLICTS_SOLUTIONS );
182     wxASSERT( item9 );
183     item0->Add( item9, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
184
185 #ifdef __WXGTK__
186     wxButton *contextButton = new wxContextHelpButton( parent );
187     item1->Add( contextButton, 0, wxALIGN_CENTRE|wxALL, 5 );
188 #endif
189
190     parent->SetAutoLayout( TRUE );
191     parent->SetSizer( item0 );
192
193     // N.B. I find I have to call Layout, then Fit, to make this
194     // work.
195     parent->Layout();
196     item0->Fit( parent );
197     item0->SetSizeHints( parent );
198
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."));
206
207 #if __WXGTK__
208     parent->FindWindow( wxID_CONTEXT_HELP )->SetHelpText(_("Invokes context-sensitive help for the clicked-on window."));
209 #endif
210 }
211
212 void ecResolveConflictsDialog::OnInitDialog(wxInitDialogEvent& event)
213 {
214     wxDialog::OnInitDialog(event);
215
216     // Select the first item and fill the solution set
217     m_conflictsCtrl->AddConflicts(m_conflicts);
218     
219     if (m_parConflictsOfInterest && m_parConflictsOfInterest->Number()>0)
220     {
221         wxList &arConflictsOfInterest = *m_parConflictsOfInterest;
222         int i, j;
223         for ( i = m_conflictsCtrl->GetItemCount() - 1; i >= 0; --i )
224         {
225             for ( j = arConflictsOfInterest.Number() - 1; j>=0; --j )
226             {
227                 CdlConflict conflict = (CdlConflict)m_conflictsCtrl->GetItemData(i);
228                 if ( ((CdlConflict) arConflictsOfInterest[j]) == conflict )
229                 {
230                     m_conflictsCtrl->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
231                     m_conflictsCtrl->EnsureVisible(i);
232                     arConflictsOfInterest.DeleteObject(arConflictsOfInterest[j]);
233                     break;
234                 }
235             }
236         }
237     } else
238     {
239         for ( int i = m_conflictsCtrl->GetItemCount()-1; i>=0; --i )
240         {
241             m_conflictsCtrl->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
242         }
243     }
244     m_conflictsCtrl->SetFocus();
245 }
246
247 void ecResolveConflictsDialog::OnContinue(wxCommandEvent& event)
248 {
249     // Ensure we have the current conflict check array
250     int i;
251     for (i = 0; i < m_conflictsCtrl->GetItemCount(); i++)
252     {
253         if (m_conflictsCtrl->GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
254             RemoveConflictSolutions((CdlConflict) m_conflictsCtrl->GetItemData(i));
255     }
256
257     // Dismiss the window
258     EndModal(wxID_OK);
259
260     std::list<CdlConflict>::const_iterator conf_i;
261
262     for (conf_i= m_conflicts.begin (); conf_i != m_conflicts.end (); conf_i++) // for each conflict
263     {
264         CdlConflict conflict=*conf_i;
265         //int nSolutions=conflict->get_solution().size();
266         SolutionInfo &info=Info(conflict);
267         int nIndex=0;
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());
276                 bool rc = TRUE;
277                 wxString str;
278                 try
279                 {
280                     switch(flavor)
281                     {
282                     case CdlValueFlavor_None :
283                         str = wxT("set CdlValueFlavor_None");
284                         rc = FALSE;
285                         break;
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);
289                         break;
290                     case CdlValueFlavor_BoolData :
291                         {
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
295                             // set a NEW value.
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);
299                         }
300                         break;
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);
304                         break;
305                     }
306                 }
307                 catch(...)
308                 {
309                     rc = FALSE;
310                 }
311                 if(rc)
312                 {
313                     wxGetApp().GetConfigToolDoc()->Modify(TRUE);
314                 } else
315                 {
316                     wxString msg;
317                     msg.Printf(_("Failed to %s\n"), (const wxChar*) str);
318                     wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
319                 }
320             }
321         }
322     }
323 }
324
325 void ecResolveConflictsDialog::OnAll(wxCommandEvent& event)
326 {
327     SetAll(TRUE);
328 }
329
330 void ecResolveConflictsDialog::OnNone(wxCommandEvent& event)
331 {
332     SetAll(FALSE);
333 }
334
335 void ecResolveConflictsDialog::SetAll(bool bOnOff)
336 {
337     long i;
338     for ( i = m_solutionsCtrl->GetItemCount()-1; i >= 0; --i)
339     {
340         m_solutionsCtrl->SetChecked(i, bOnOff);
341     }
342 }
343
344 // Update All button
345 void ecResolveConflictsDialog::OnUpdateAll(wxUpdateUIEvent& event)
346 {
347     if (!m_solutionsCtrl)
348         return;
349     
350     int nCheckCount=0;
351     int nItemCount = m_solutionsCtrl->GetItemCount();
352     int i;
353     for (i=nItemCount-1;i>=0;--i)
354     {
355         nCheckCount+=m_solutionsCtrl->IsChecked(i);
356     }
357     event.Enable(nItemCount>0 && nCheckCount<nItemCount);
358 }
359
360 // Update None button
361 void ecResolveConflictsDialog::OnUpdateNone(wxUpdateUIEvent& event)
362 {
363     if (!m_solutionsCtrl)
364         return;
365     
366     int nCheckCount=0;
367     int nItemCount=m_solutionsCtrl->GetItemCount();
368     int i;
369     for (i=nItemCount-1;i>=0;--i){
370         nCheckCount+=m_solutionsCtrl->IsChecked(i);
371     }
372     event.Enable(nItemCount>0 && nCheckCount>0);
373 }
374
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()
379 {
380     ecConfigItem *pItem = m_conflictsCtrl->AssociatedItem(m_nContextItem, m_nContextRow);
381     if (pItem) {
382         if (wxGetApp().GetTreeCtrl())
383             wxGetApp().GetTreeCtrl()->SelectItem(pItem->GetTreeItem());
384     }
385 }
386
387 void ecResolveConflictsDialog::RemoveConflictSolutions(CdlConflict conflict)
388 {
389     SolutionInfo &info=Info(conflict);
390     int i, j, k;
391     for ( i = 0; i < info.nCount; i++ )
392     {
393         int nItem=info.arItem[i];
394         wxASSERT(nItem>=0);
395         info.arItem[i] = (m_solutionsCtrl->IsChecked(nItem) ? SolutionInfo::CHECKED:SolutionInfo::UNCHECKED);
396         int nRefs = m_solutionsCtrl->GetItemData(nItem);
397         if (1 == nRefs)
398         {
399             m_solutionsCtrl->DeleteItem(nItem);
400             for ( k = 0; k < m_conflictsCtrl->GetItemCount(); k++ )
401             {
402                 SolutionInfo &info2 = Info((CdlConflict)m_conflictsCtrl->GetItemData(k));
403                 for ( j = 0; j < info2.nCount; j++)
404                 {
405                     if (info2.arItem[j] > nItem)
406                     {
407                         info2.arItem[j] --;
408                     }
409                 }
410             }
411         } else
412         {
413             m_solutionsCtrl->SetItemData(nItem, nRefs-1);
414         }
415     }
416 }
417
418 void ecResolveConflictsDialog::AddConflictSolutions(CdlConflict conflict)
419 {
420     // SolutionInfo allows each conflict to know which solutions have been found for it
421     SolutionInfo &info=Info(conflict);
422     
423     const std::vector<std::pair<CdlValuable, CdlValue> >&Solution=conflict->get_solution();
424     
425     int i=0;
426     for (std::vector<std::pair<CdlValuable, CdlValue> >::const_iterator soln_i = Solution.begin();
427          soln_i != Solution.end(); soln_i++)
428     {
429         CdlValuable valuable = soln_i->first;
430         CdlValue value = soln_i->second;
431         CdlValueFlavor flavor = valuable->get_flavor();
432         
433         wxString strValue;
434         switch(flavor)
435         {
436         case CdlValueFlavor_None :
437             break;
438         case CdlValueFlavor_Bool :
439             strValue = value.is_enabled() ? _("Enabled") : _("Disabled");
440             break;
441         case CdlValueFlavor_BoolData :
442             strValue.Printf(wxT("%s, %s"), (const wxChar*) (value.is_enabled() ? _("Enabled") : _("Disabled")), (const wxChar*) value.get_value().c_str());
443             break;
444         case CdlValueFlavor_Data :
445             strValue = value.get_value().c_str();
446             break;
447         }
448         
449         const wxString strName(soln_i->first->get_name().c_str());
450
451         long nIndex = m_solutionsCtrl->FindItem(0, strName);
452         wxListItem listItem;
453         listItem.m_mask = wxLIST_MASK_TEXT;
454         listItem.m_itemId = nIndex;
455         listItem.m_col = 1;
456         if (nIndex != -1)
457             m_solutionsCtrl->GetItem(listItem);
458
459         if (-1 == nIndex || strValue != listItem.m_text)
460         {
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);
466
467             wxASSERT(info.arItem[i]<0);
468
469             m_solutionsCtrl->SetChecked(nIndex, SolutionInfo::CHECKED==info.arItem[i]);
470         } else {
471             // We do - to avoid duplicates, increment the "ref count"
472             m_solutionsCtrl->SetItemData(nIndex, m_solutionsCtrl->GetItemData(nIndex)+1);
473         }
474         info.arItem[i++]=nIndex; 
475
476     }
477     wxStaticText* staticCtrl = (wxStaticText*) FindWindow(ecID_CONFLICTS_MSG);
478
479     if(0==i){
480         staticCtrl->SetLabel(_("No solution is available for this conflict"));
481         m_solutionsCtrl->Show(FALSE);
482     } else {
483         staticCtrl->SetLabel(_("Proposed solution:"));
484         m_solutionsCtrl->Show(TRUE);
485         // TODO (if necessary)
486 #if 0
487         m_List.SetColumnWidth(0,LVSCW_AUTOSIZE);
488         CRect rect;
489         m_List.GetClientRect(rect);
490         m_List.SetColumnWidth(1,rect.Width()-m_List.GetColumnWidth(0));
491 #endif
492     }
493 }
494
495 ecResolveConflictsDialog::SolutionInfo & ecResolveConflictsDialog::Info(const CdlConflict conflict)
496 {
497   SolutionInfo *pInfo = (SolutionInfo*) m_Map.Get((long) conflict);
498   return * pInfo;
499 }
500
501 void ecResolveConflictsDialog::OnConflictSelected(wxListEvent& event) 
502 {
503     CdlConflict conflict=(CdlConflict) m_conflictsCtrl->GetItemData(event.GetIndex());
504
505     if (1 == m_solutionsCtrl->GetSelectedItemCount())
506     {
507         // TODO ??
508         // GetDlgItem(IDC_STATIC1)->ShowWindow(SW_HIDE);
509         m_solutionsCtrl->Show(TRUE);
510     }
511     AddConflictSolutions(conflict);
512 }
513
514 void ecResolveConflictsDialog::OnConflictDeselected(wxListEvent& event) 
515 {
516     CdlConflict conflict=(CdlConflict) m_conflictsCtrl->GetItemData(event.GetIndex());
517     
518     RemoveConflictSolutions(conflict);
519 }
520
521
522 #if 0
523 // TODO?
524
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) 
529 {
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);
536   }
537   *pResult = 0;
538   return false; // not handled
539 }
540
541 // TODO
542 BOOL ecResolveConflictsDialog::OnRClick(UINT, LPNMITEMACTIVATE pnmv, LRESULT* pResult) 
543 {
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);
550         Menu menu;
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"));
553 #ifndef PLUGIN
554     SuppressNextContextMenuMessage();
555 #endif
556     menu.TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, pt.x,pt.y,this);
557   }
558
559   *pResult = 0;
560   return TRUE; // handled
561 }
562
563 #endif
564