proppanel_buildsystem.cpp

00001 
00002 // Name:        proppanel_buildsystem.cpp
00003 // Purpose:     wxPackagePropertiesPanel
00004 //              (stuff for handling the "buildsystem" page)
00005 // Author:      Francesco Montorsi
00006 // Modified by:
00007 // Created:     28/06/2006 19:22:47
00008 // RCS-ID:      $Id: proppanel_buildsystem.cpp,v 1.8 2007/01/28 14:35:29 frm Exp $
00009 // Copyright:   (c) 2006 Julian Smart, Francesco Montorsi
00010 // Licence:     wxWidgets license
00012 
00013 
00014 // For compilers that support precompilation, includes "wx/wx.h".
00015 #include "wx/wxprec.h"
00016 
00017 #ifdef __BORLANDC__
00018 #pragma hdrstop
00019 #endif
00020 
00021 #ifndef WX_PRECOMP
00022 #include "wx/wx.h"
00023 #endif
00024 
00025 #include "guipkg/proppanel.h"
00026 #include "guipkg/sourceeditctrl.h"
00027 #include "guipkg/opteditdlg.h"
00028 #include "guipkg/cmdeditdlg.h"
00029 #include "guipkg/optlistctrl.h"
00030 #include "guipkg/optpresetchooserdlg.h"
00031 #include "guipkg/cmdpresetchooserdlg.h"
00032 
00033 #include "guicmn/commandlistbox.h"
00034 
00035 #include "wxp/package.h"
00036 #include "wxp/wxp.h"
00037 #include "wxp/packagewxp.h"
00038 
00039 #include "wx/miscutils.h"
00040 
00041 
00042 
00043 // ----------------------------------------------------------------------------
00044 // Global helpers
00045 // ----------------------------------------------------------------------------
00046 
00047 // some globals wxPackageCommandOption helpers
00048 
00049 wxPackageCommandOption &wxGetPackageCommandOptionFromListbox(wxListBox *lb, unsigned int idx)
00050 { return *((wxPackageCommandOption *)lb->GetClientData(idx)); }
00051 
00052 void wxUpdatePackageCommandOptionInListbox(wxListBox *lb, unsigned int idx,
00053                                            const wxPackageCommandOption &opt)
00054 { wxGetPackageCommandOptionFromListbox(lb, idx) = opt; }
00055 
00056 
00057 
00058 // ----------------------------------------------------------------------------
00059 // wxPackagePropertiesPanel - build system stuff - I/O
00060 // ----------------------------------------------------------------------------
00061 
00062 void wxPackagePropertiesPanel::InitBuildSystemPage()
00063 {
00064     m_pBuildSystemType->Append(wxArrayString(wxPBST_MAX, wxPackageBuildSystemTypeName));
00065     m_pBuildSystemStage->Append(wxArrayString(wxPBSS_MAX, wxPackageBuildSystemStageName));
00066     m_pBuildSystemType->Select(0);
00067     m_pBuildSystemStage->Select(0);
00068 
00069     // fake event to initialize the formats choice control
00070     wxCommandEvent fake;
00071     OnBuildSystemType(fake);        // this will update all filters
00072 
00073     UpdateOptions();
00074     UpdateCommands();
00075 }
00076 
00077 void wxPackagePropertiesPanel::GetBuildSystemPackageInfo(wxPackageInfo &ret) const
00078 {
00079     // BUILD SYSTEM info
00080     ret.SetBuildSysHref(m_strBuildSystemHref);
00081     ret.SetBuildSystemType(GetSelBuildSystemType());
00082     ret.SetBuildSysOptions(m_pBuildSysOptions->GetOptions());
00083 
00084     // NB: we cannot use wxCheckListBox2Flags as m_pFormats contains only those
00085     //     formats supported by selected build system and not all wxPackageCompilerFormat
00086     ret.SetSupportedFormats(GetCompilerFormats());
00087 
00088     for (size_t i=0; i<wxPBSS_MAX; i++)
00089         ret.SetBuildSysCommands(wxIdx2PackageBuildSystemStage(i), m_commands[i]);
00090 }
00091 
00092 void wxPackagePropertiesPanel::DoSetBuildSystemPackageInfo(const wxPackageInfo &p)
00093 {
00094     // BUILD SYSTEM info
00095     m_strBuildSystemHref = p.GetBuildSystemHref();
00096 
00097     if (p.GetBuildSystemType() != wxPBST_INVALID)
00098         m_pBuildSystemType->SetSelection(
00099                 wxPackageBuildSystemType2Idx(p.GetBuildSystemType()));
00100     else
00101         m_pBuildSystemType->SetSelection(0);
00102 
00103     // false events to force m_formats & m_pFormats update
00104     wxCommandEvent ev;
00105     OnBuildSystemType(ev);
00106 
00107     // NB: we cannot use wxFlags2CheckListBox to update m_pFormats
00108     //     as it contains only the formats filtered for current build system type !
00109     wxCheckAll(m_pFormats, false);
00110     for (size_t i=0; i<m_pFormats->GetCount(); i++)
00111         if ((p.GetSupportedBuildSysFormats() & m_formats[i]) != 0)
00112             m_pFormats->Check(i);
00113 
00114     // update filters
00115     m_pBuildSysOptions->SetCompilerFormats(p.GetSupportedBuildSysFormats());
00116     m_pBuildSysCommands->SetCompilerFormats(p.GetSupportedBuildSysFormats());
00117 
00118     // update options
00119     m_pBuildSysOptions->SetOptions(p.GetBuildSysOptions());
00120     UpdateOptions();
00121 
00122     for (size_t i=0; i<wxPBSS_MAX; i++)
00123     {
00124         m_commands[i] = p.GetCmdForStage(wxIdx2PackageBuildSystemStage(i));
00125         m_targets[i] = m_commands[i].GetTargetsStr();
00126     }
00127 
00128     int idx = m_pBuildSystemStage->GetSelection();
00129     m_pTargets->SetValue(m_targets[idx]);
00130 
00131     // update commands
00132     m_pBuildSysCommands->SetCommands(m_commands[idx]);
00133     UpdateCommands();
00134 
00135     // reset modified flag
00136     m_bModified=false;
00137 
00138     // NOTE: this function won't call UpdateXML(); the SetPackageInfo()
00139     //       overloads will do that
00140 }
00141 
00142 bool wxPackagePropertiesPanel::IsBuildSystemPageOk() const
00143 {
00144     bool isok = true;
00145 
00146     // check formats
00147     if (wxCheckListBox2Flags(m_pFormats) == 0)
00148     {
00149         wxLogWarning(wxT("Please check at least one compiler format as supported"));
00150         isok = false;
00151     }
00152 
00153     // check options
00154     if (m_pBuildSysOptions->GetOptions().GetCount() == 0)
00155     {
00156         wxLogWarning(wxT("No build options available for this package ?"));
00157         isok = false;
00158     }
00159 
00160     for (size_t i=0; i<wxPBST_MAX; i++)
00161     {
00162         wxString stagename = 
00163             wxPackageBuildSystemStage2String(wxIdx2PackageBuildSystemStage(i));
00164 
00165         if (m_commands[i].GetCount() == 0)
00166         {
00167             wxLogWarning(wxT("No commands for the '%s' build system stage ?"),
00168                          stagename.c_str());
00169             isok = false;
00170         }
00171 
00172         if (m_targets[i].IsEmpty())
00173         {
00174             wxLogWarning(wxT("No targets for the '%s' build system stage ?"),
00175                          stagename.c_str());
00176             isok = false;
00177         }
00178     }
00179 
00180     return isok;
00181 }
00182 
00183 
00184 // ----------------------------------------------------------------------------
00185 // wxPackagePropertiesPanel - build system stuff 
00186 // ----------------------------------------------------------------------------
00187 
00188 bool wxPackagePropertiesPanel::GetBuildSysOption(wxPackageCommandOption *ret,
00189                                                  const wxPackageCommandOption &initial)
00190 {
00191     wxPackageOptionEditDlg dlg(this);
00192     dlg.SetOption(initial);
00193     if (dlg.ShowModal() == wxID_OK)
00194     {
00195         wxPackageCommandOption opt(dlg.GetOption());
00196         wxString presetname;
00197 
00198         if (initial.GetName() != opt.GetName())
00199         {
00200             // check the new name
00201             if (IsPresetOption(opt.GetName(), &presetname))
00202             {
00203                 // this name conflicts with the name of an option in one of the
00204                 // presets that are in use !
00205                 wxLogError(wxT("Cannot use the '%s' name.\nIt's the name of an option contained in the '%s' preset, which is in use."),
00206                            opt.GetName().c_str(), presetname.c_str());
00207                 return false;
00208             }
00209             else if (IsUserOption(opt.GetName()))
00210             {
00211                 wxLogError(wxT("Cannot use the '%s' name.\nIt's the name of another option."),
00212                            opt.GetName().c_str());
00213                 return false;
00214             }
00215         }
00216 
00217         // no conflicts
00218         if (ret) *ret = opt;
00219         return true;
00220     }
00221 
00222     return false;
00223 }
00224 
00225 bool wxPackagePropertiesPanel::GetBuildSysCommand(wxPackageCommand *ret,
00226                                                   wxPackageBuildSystemStage stage,
00227                                                   const wxPackageCommand &initial)
00228 {
00229     wxPackageCommandEditDlg dlg(this);
00230     dlg.SetCommand(initial, stage);
00231     if (dlg.ShowModal() == wxID_OK)
00232     {
00233         wxPackageCommand cmd(dlg.GetCommand());
00234         if (ret) *ret = cmd;
00235         return true;
00236     }
00237 
00238     return false;
00239 }
00240 
00241 void wxPackagePropertiesPanel::UpdateOptions()
00242 {
00243     const wxPackageCommandOptionArray &arr = m_pBuildSysOptions->GetOptions();
00244 
00245     // update the "used presets" label:
00246     wxString str;
00247     wxPackageCommandOptionArrayHashMap::iterator it;
00248     for( it = wxPresetXMLDescriptor::s_hashmapOptions.begin();
00249          it != wxPresetXMLDescriptor::s_hashmapOptions.end(); ++it )
00250     {
00251         wxString name = it->first;
00252         wxPackageCommandOptionArray &value = it->second;
00253 
00254         if (arr.Contains(value))
00255             str += name + wxT(", ");
00256     }
00257 
00258     if (str.IsEmpty())
00259         str = wxT("none");
00260     else
00261         str = str.RemoveLast().RemoveLast();
00262     m_pOptionPresets->SetLabel(str);
00263 }
00264 
00265 void wxPackagePropertiesPanel::UpdateCommands()
00266 {
00267     // update the "used presets" label:
00268     wxString str;
00269     wxStringHashMap h;
00270     wxPackageCommandSetHashMap::iterator it;
00271     for( it = wxPresetXMLDescriptor::s_hashmapCommands.begin();
00272          it != wxPresetXMLDescriptor::s_hashmapCommands.end(); ++it )
00273     {
00274         wxString name = it->first;
00275         wxPackageCommandSet &set = it->second;
00276 
00277         if (set.IsUsedBy(m_commands, h))
00278             str += name + wxT(", ");
00279     }
00280 
00281     if (str.IsEmpty())
00282         str = wxT("none");
00283     else
00284         str = str.RemoveLast().RemoveLast();
00285     m_pCommandPresets->SetLabel(str);
00286 }
00287 
00288 bool wxPackagePropertiesPanel::IsPresetOption(const wxString &optname,
00289                                               wxString *presetname) const
00290 {
00291     wxArrayString presets = wxStringTokenize(m_pOptionPresets->GetLabel(), wxT(","));
00292 
00293     for (size_t i=0; i<presets.GetCount(); i++)
00294     {
00295         wxPackageCommandOptionArrayHashMap &h = wxPresetXMLDescriptor::s_hashmapOptions;
00296 
00297         // this check is important to avoid to call h[wxT("some-dummy-string")]
00298         // which would generate a new option array!
00299         if (h.count(presets[i]) > 0)
00300         {
00301             if (h[presets[i]].IndexByName(optname) != wxNOT_FOUND)
00302             {
00303                 if (presetname) *presetname = presets[i];
00304                 return true;
00305             }
00306         }
00307     }
00308 
00309     return false;
00310 }
00311 
00312 bool wxPackagePropertiesPanel::IsUserOption(const wxString &optname) const
00313 { 
00314     if (m_pBuildSysOptions->GetOptions().ContainsItemNamed(optname))
00315         return true;
00316     if (IsPresetOption(optname, NULL))
00317         return true;
00318 
00319     return false;
00320 }
00321 
00322 long wxPackagePropertiesPanel::GetCompilerFormats() const
00323 {
00324     long fmt = 0;
00325     for (size_t i=0; i<m_pFormats->GetCount(); i++)
00326         if (m_pFormats->IsChecked(i))
00327             fmt |= m_formats[i];
00328 
00329     return fmt;
00330 }
00331 
00332 
00333 // ----------------------------------------------------------------------------
00334 // wxPackagePropertiesPanel - event handlers
00335 // ----------------------------------------------------------------------------
00336 
00337 void wxPackagePropertiesPanel::OnBuildSystemType(wxCommandEvent &)
00338 {
00339     wxPackageBuildSystemType t =
00340             wxIdx2PackageBuildSystemType(m_pBuildSystemType->GetSelection());
00341     wxASSERT(t != wxPBST_INVALID);
00342 
00343     // update the format wxCheckListBox control to show only the formats available
00344     // for the currently selected build system
00345     m_pFormats->Clear();
00346     for (size_t i=0; i<wxPCF_MAX; i++)
00347     {
00348         wxPackageCompilerFormat curr = wxIdx2PackageCompilerFormat(i);
00349         if (wxIsCompilerFormatSupportedBy(curr, t))
00350         {
00351             int last = m_pFormats->Append(wxPackageCompilerFormat2String(curr));
00352 
00353             // unfortunately we cannot use client data with a wxCheckListBox
00354             m_formats[last] = curr;
00355 
00356             // make all formats checked at the beginning
00357             m_pFormats->Check(last);
00358         }
00359     }
00360 
00361     // then, select the first of those formats
00362     m_pFormats->Select(0);
00363 
00364     // update filters
00365     m_pBuildSysOptions->SetBuildSystemType(t);
00366     m_pBuildSysCommands->SetBuildSystemType(t);
00367 
00368     // fake event
00369     wxCommandEvent fake;
00370     OnBuildSystemFormatCheck(fake);
00371 
00372     OnUserChange();
00373 }
00374 
00375 void wxPackagePropertiesPanel::OnBuildSystemFormatCheck(wxCommandEvent &)
00376 {
00377     // get the wxPackageCompilerFormat flag
00378     long fmt = GetCompilerFormats();
00379 
00380     // update filters
00381     m_pBuildSysOptions->SetCompilerFormats(fmt);
00382     m_pBuildSysCommands->SetCompilerFormats(fmt);
00383 
00384     OnUserChange();
00385 }
00386 
00387 void wxPackagePropertiesPanel::OnBuildSystemStage(wxCommandEvent &)
00388 {
00389     int idx = m_pBuildSystemStage->GetSelection();
00390 
00391     // save targets & commands for old stage
00392     TransferDataFromWindow();
00393 
00394     // update targets & commands for this stage
00395     m_pTargets->SetValue(m_targets[idx]);
00396     m_pBuildSysCommands->SetCommands(m_commands[idx]);
00397 
00398     m_nLastStage=idx;
00399 
00400     OnUserChange();
00401 }
00402 
00403 void wxPackagePropertiesPanel::OnBuildSystemButton(wxCommandEvent &ev)
00404 {
00405     OnUserChange();
00406 
00407     switch (ev.GetId())
00408     {
00409     case ID_PROP_NEW_OPTION:
00410         {
00411             wxPackageCommandOption opt;
00412 
00413             // start with all conditions checked
00414             opt.GetCondition().SetAlwaysTrue();
00415 
00416             if (GetBuildSysOption(&opt, opt))
00417             {
00418                 m_pBuildSysOptions->GetOptions().Add(opt);
00419                 m_pBuildSysOptions->TransferDataToWindow();
00420                 UpdateOptions();
00421             }
00422         }
00423         break;
00424 
00425     case ID_PROP_NEW_COMMAND:
00426         {
00427             wxPackageCommand cmd;
00428             int idx = m_pBuildSystemStage->GetSelection();
00429             wxPackageBuildSystemStage stage = wxIdx2PackageBuildSystemStage(idx);
00430 
00431             // start with all conditions checked except for the stage
00432             cmd.GetCondition().SetAlwaysTrue();
00433             cmd.GetCondition().SetStages(stage);
00434 
00435             if (GetBuildSysCommand(&cmd, stage, cmd))
00436             {
00437                 m_pBuildSysCommands->Append(cmd);
00438                 UpdateCommands();
00439             }
00440         }
00441         break;
00442 
00443     case ID_PROP_DELETE_OPTION:
00444         {
00445             wxString optname(m_pBuildSysOptions->GetSelectedOptName()), presetname;
00446             if (optname.IsEmpty())
00447             {
00448                 // the selected item is an option group, not an option!
00449                 // ignore this command
00450                 return;
00451             }
00452             else if (IsPresetOption(optname, &presetname))
00453             {
00454                 int reply = wxMessageBox(
00455                     wxString::Format(
00456                         wxT("Are you sure that you want to delete an option which belongs to the '%s' preset?\n\nIf you do, this package won't use that preset anymore and all its other options\nwill be copied in the WXP file making it longer (and hard to maintain/review)..."),
00457                         presetname.c_str()),
00458                     wxT("Question"), wxYES_NO|wxICON_QUESTION, this);
00459                 if (reply == wxID_YES)
00460                 {
00461                     m_pBuildSysOptions->DeleteSelected();
00462                     UpdateOptions();
00463                 }
00464             }
00465             else
00466             {
00467                 m_pBuildSysOptions->DeleteSelected();
00468                 UpdateOptions();
00469             }
00470         }
00471         break;
00472 
00473     case ID_PROP_DELETE_COMMAND:
00474         m_pBuildSysCommands->DeleteSelected();
00475         UpdateCommands();
00476         break;
00477 
00478     case ID_PROP_RESET_COMMANDS:
00479         {
00480             if (wxPresetXMLDescriptor::GetCommandPresetNamesFor(GetSelBuildSystemType()).GetCount() == 0)
00481             {
00482                 wxLogMessage(wxT("No presets for the currently selected build system type"));
00483                 return;
00484             }
00485 
00486             wxPackageCommandPresetChooserDlg dlg(this, wxID_ANY, GetSelBuildSystemType());
00487             if (dlg.ShowModal() == wxID_OK)
00488             {
00489                 const wxPackageCommandSet &arr = dlg.GetSelectedPreset();
00490 
00491                 wxStringHashMap vars;
00492                 for (size_t i=0; i < arr.GetVars().GetCount(); i++)
00493                 {
00494                     wxString curr = arr.GetVars().Item(i);
00495 
00496                     wxString msg;
00497                     msg.Printf(wxT("Please provide the value of the '%s' variable\n")
00498                                wxT("for the '%s' command preset."),
00499                                curr.c_str(), dlg.GetSelectedPresetName().c_str());
00500                     wxString txt = wxGetTextFromUser(msg, wxT("Input variable value"),
00501                                                      wxEmptyString, this);
00502                     if (txt.IsEmpty())
00503                         return;
00504                     vars[curr] = txt;
00505                 }
00506 
00507                 // set selected cmd preset
00508                 for (size_t i=0; i<wxPBSS_MAX; i++)
00509                 {
00510                     m_commands[i].Clear();
00511 
00512                     wxPackageBuildSystemStage stage = wxIdx2PackageBuildSystemStage(i);
00513                     for (size_t j=0; j<arr.GetCount(); j++)
00514                     {
00515                         if (arr[j].GetCondition().GetStages() & stage)
00516                         {
00517                             m_commands[i].Add(arr[j]);
00518                             m_commands[i].AddKeywords(vars);
00519                         }
00520                     }
00521                 }
00522 
00523                 // update the control, too
00524                 int idx = m_pBuildSystemStage->GetSelection();
00525                 m_pBuildSysCommands->SetCommands(m_commands[idx]);
00526 
00527                 // update the "presets used" label
00528                 UpdateCommands();
00529             }
00530         }
00531         break;
00532 
00533     case ID_PROP_ADD_OPTPRESET:
00534         {
00535             if (wxPresetXMLDescriptor::GetOptionPresetNamesFor(GetSelBuildSystemType()).GetCount() == 0)
00536             {
00537                 wxLogMessage(wxT("No presets for the currently selected build system type"));
00538                 return;
00539             }
00540 
00541             wxPackageOptionPresetChooserDlg dlg(this, wxID_ANY, GetSelBuildSystemType());
00542             if (dlg.ShowModal() == wxID_OK)
00543             {
00544                 // add selected option preset
00545                 wxPackageCommandOptionArray arr = m_pBuildSysOptions->GetOptions();
00546                 WX_APPEND_ARRAY(arr, dlg.GetSelectedPreset());
00547                 m_pBuildSysOptions->SetOptions(arr);
00548 
00549                 // update the "presets used" label
00550                 UpdateOptions();
00551             }
00552         }
00553         break;
00554     }
00555 }
00556 
00557 void wxPackagePropertiesPanel::OnBuildSystemListBoxDClick(wxCommandEvent &ev)
00558 {
00559     OnUserChange();
00560 
00561     switch (ev.GetId())
00562     {
00563         case ID_PROP_BUILDSYS_COMMANDS:
00564         {
00565             int stageidx = m_pBuildSystemStage->GetSelection();
00566             int idx = m_pBuildSysCommands->GetSelection();
00567             if (idx == wxNOT_FOUND)
00568             {
00569                 // this may happen on wxMSW 's listboxes when they have > 0 items
00570                 // and the user clicks on the empty space
00571                 return;
00572             }
00573 
00574             wxPackageCommand newentry;
00575             if (GetBuildSysCommand(&newentry, wxIdx2PackageBuildSystemStage(stageidx),
00576                                    m_pBuildSysCommands->GetCommand(idx)))
00577             {
00578                 m_pBuildSysCommands->SetCommand(idx, newentry);
00579                 UpdateCommands();
00580             }
00581         }
00582         break;
00583     }
00584 }
00585 
00586 void wxPackagePropertiesPanel::OnOptionDClick(wxCommandEvent &ev)
00587 {
00588     wxString optname(ev.GetString()), presetname;
00589     if (IsPresetOption(optname, &presetname))
00590     {
00591         int reply = wxMessageBox(
00592             wxString::Format(
00593                 wxT("Are you sure you want to edit an option which belongs to the '%s' preset?\nIf you do, this package won't use that preset anymore and all its options\nwill be copied in the WXP file making it longer (and hard to maintain/review)..."),
00594                 presetname.c_str()),
00595             wxT("Question"), wxYES_NO|wxICON_QUESTION, this);
00596         if (reply == wxID_NO)
00597             return;
00598     }
00599 
00600     wxPackageCommandOptionArray &arr = m_pBuildSysOptions->GetOptions();
00601     wxPackageCommandOption newentry, initial = arr.ItemByName(optname);
00602     if (GetBuildSysOption(&newentry, initial))
00603     {
00604         arr.UpdateOption(newentry);
00605         m_pBuildSysOptions->TransferDataToWindow();
00606         UpdateOptions();
00607     }
00608 
00609     OnUserChange();
00610 }
00611 
00612 void wxPackagePropertiesPanel::OnBuildSystemPageUpdateUI(wxUpdateUIEvent &WXUNUSED(ev))
00613 {
00614     FindWindowById(ID_PROP_DELETE_COMMAND)->Enable(m_pBuildSysCommands->GetSelection() != wxNOT_FOUND);
00615     FindWindowById(ID_PROP_DELETE_OPTION)->Enable(m_pBuildSysOptions->GetSelection().IsOk());
00616 }
00617 

Generated on Thu Feb 1 22:14:31 2007 for wxWidgets Package Manager by  doxygen 1.5.1-p1