home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / DIAGXPRT.PAK / SETUP.CPP < prev    next >
C/C++ Source or Header  |  1995-08-29  |  21KB  |  808 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //----------------------------------------------------------------------------
  4. #include  <owl\owlpch.h>
  5. #include  <owl\dialog.h>
  6. #include  <owl\clipboar.h>
  7. #include  <owl\clipview.h>
  8. #include  "diagxprt.rh"
  9. #include  "setup.h"
  10. #include  "diagxprt.h"
  11. #include  <stdio.h>
  12.  
  13. //
  14. //  The diagnostic setup dialog box is divided in 2 main groups:
  15. //  * the system group (TSysGroup->TGroup);
  16. //  * the user group (TUsrGroup->TGroup).
  17. //
  18. //  Each group is a list of items (TSetupItem).
  19. //  Items belonging to the system group (TSysItem->TSetupItem) are
  20. //  different than items belonging to the user group (TUsrItem->TSetupItem)
  21. //  in that the setup infos are not maintained the same way in OWL.INI.
  22. //
  23. //  Each item TSysItem and TUsrItem is attached to a set of child windows
  24. //  in the dialog box. Each such set of windows is abstracted thru a class:
  25. //  TUsrWindow and TSysWindow respectively. Each of those classes is
  26. //  generated by a class template, which parametrizes the exact contents
  27. //  of the set of windows: TRadioButton/TRadioButton and TStatic/TEdit resp.
  28. //
  29. //  The number of windows set is limited (by the area in the dialog box);
  30. //  the number of items is NOT limited. Scroll bars are displayed when
  31. //  necessary. Those scrollbars are abstracted thru the class TGroupScroll.
  32. //  Therefore each group maintains two arrays: an array of items TItemsArray
  33. //  and an array of window sets TWindowArray.
  34. //
  35.  
  36.  
  37. //
  38. // Utility function to copy diagnostic code to clipboard so that user
  39. // can paste into appropriate source file
  40. //
  41. void
  42. CopyToClipboard(TWindow *w, char *descr, char *className)
  43. {
  44.   // Generate a C++ example on the clipboard, which is a very trivial
  45.   // string subsitution operation.
  46.   //
  47.   string pattern(
  48.     "// Diagnostic: %s\n"
  49.     "DIAG_DEFINE_GROUP_INIT(OWL_INI, %s, 1, 0);\n"
  50.     "//TRACEX(%s, errLevel, \042A comment \042 << aFunction());\n"
  51.    );
  52.  
  53.   pattern.substring("%s") = descr;
  54.   pattern.substring("%s") = className;
  55.   pattern.substring("%s") = className;
  56.  
  57.   TClipboard& c = w->OpenClipboard();
  58.   c.EmptyClipboard();
  59.   HANDLE hData = GlobalAlloc(GMEM_SHARE, pattern.length()+1);
  60.   char far* pData = (char far*)GlobalLock(hData);
  61.  
  62.   pattern.copy(pData, pattern.length()+1);
  63.  
  64.   GlobalUnlock(hData);
  65.   c.SetClipboardData(CF_TEXT, hData);
  66.  
  67.   c.CloseClipboard();  // Clipboard is responsible for freeing hData
  68. }
  69.  
  70. //
  71. //  class TSetupItem
  72. //
  73.  
  74. TSetupItem::TSetupItem(char *C, char *D) : Enable(0), level(0)
  75. {
  76.   Class = C;
  77.   Descr = D;
  78. }
  79.  
  80. void
  81. TSetupItem::operator =(TBaseSetupWindow& w)
  82. {
  83.   // Unmap from a physical set of windows: set the enability and
  84.   // warning level accordingly to the setup window:
  85.   //
  86.   SetEnable(w.GetEnable());
  87.   SetLevel(w.GetLevel());
  88. }
  89.  
  90. void
  91. TSetupItem::Load()
  92. {
  93.   // Loads itself from .ini file - loads the diagnostic classname and the
  94.   // diagnostic description:
  95.   //
  96.   char b[80];
  97.   GetPrivateProfileString(GetSection(), Class.c_str(), "0 0",
  98.                           b, sizeof(b), GetIniFile());
  99.   sscanf(b, "%d %d", &bEnable, &level);
  100.   if (Descr == "") {
  101.     GetPrivateProfileString(GetSectionDesc(), Class.c_str(), Class.c_str(),
  102.                             b, sizeof(b), GetIniFile());
  103.     Descr = b;
  104.   }
  105. }
  106.  
  107. void
  108. TSetupItem::Save()
  109. {
  110.   // Save itself to the .ini file - save the diagnostic classname and the
  111.   // diagnostic description:
  112.   //
  113.   char b[20];
  114.   sprintf(b, "%d %d", bEnable, level);
  115.   WritePrivateProfileString(GetSection(), Class.c_str(), b, GetIniFile());
  116.   WritePrivateProfileString(GetSectionDesc(), Class.c_str(), Descr.c_str(), GetIniFile());
  117. }
  118.  
  119. //
  120. //  class TDiagEnable
  121. //
  122.  
  123. DEFINE_RESPONSE_TABLE1(TDiagEnable, TCheckBox)
  124.   EV_NOTIFY_AT_CHILD(BN_CLICKED, BNClicked),
  125. END_RESPONSE_TABLE;
  126.  
  127. //  TDiagEnable provides an abstraction for the small check box associated
  128. //  to each setup item. This checkbox enables of disables the associated
  129. //  setup item. But the checkbox can itself be disabled (by a upper level
  130. //  checkbox).
  131. //
  132. void
  133. TDiagEnable::BNClicked()
  134. {
  135.   TCheckBox::BNClicked();
  136.   EnableWindow(TRUE);
  137. }
  138.  
  139. BOOL
  140. TDiagEnable::EnableWindow(BOOL enable)
  141. {
  142.   BOOL ret = TCheckBox::EnableWindow(enable);
  143.   if (enable)
  144.     enable = GetCheck();
  145.   if (W0) W0->EnableWindow(enable);
  146.   if (W1) W1->EnableWindow(enable);
  147.   if (S0) S0->EnableWindow(enable);
  148.   if (S1) S1->EnableWindow(enable);
  149.   return ret;
  150. }
  151.  
  152. //
  153. //  TMainEnable provides the abstraction for the main checkbox which
  154. //  enables of disables ALL the diagnostic groups. It knows how to save/load
  155. //  it state from the .ini file:
  156. //
  157. char* TMainEnable::Class = "Enabled";
  158.  
  159. TMainEnable::TMainEnable(TWindow* p, int n, TGroup* g1, TGroup* g2) :
  160.   TDiagEnable(p, n, g1, g2)
  161. {
  162.   Create();
  163.   Load();
  164. }
  165.  
  166. void
  167. TMainEnable::Load()
  168. {
  169.   char b[80];
  170.   GetPrivateProfileString(SYS_CLS, Class, "0", b, sizeof(b), SYS_INI);
  171.   SetCheck(atoi(b));
  172.   TDiagEnable::EnableWindow(TRUE);
  173. }
  174.  
  175. void
  176. TMainEnable::Save()
  177. {
  178.   char b[80];
  179.   wsprintf(b, "%d", GetCheck() != 0);
  180.   WritePrivateProfileString(SYS_CLS, Class, b, SYS_INI);
  181. }
  182.  
  183.  
  184. //
  185. //  TGroup is the base class for diagnostic groups. TGroup knows how to
  186. //  enable/disable itself (by enabling/disabling all the associated setup
  187. //  items), to load/save from the .ini file and to map/unmap its setup
  188. //  items to the associated windows sets. The purpose of the map/unmap
  189. //  operations is to allow setup items to be scrolled.
  190. //
  191.  
  192. void
  193. TGroup::EnableWindow(BOOL bEnable)
  194. {
  195.   for (int i = 0; i < Windows.GetItemsInContainer(); i++)
  196.     Windows[i]->EnableWindow(bEnable);
  197. }
  198.  
  199. void
  200. TGroup::Load()
  201. {
  202.   for (int i = 0; i < Items.GetItemsInContainer(); i++)
  203.     Items[i]->Load();
  204. }
  205.  
  206. void
  207. TGroup::Save()
  208. {
  209.   Cleanup();
  210.   for (int i = 0; i < Items.GetItemsInContainer(); i++)
  211.     Items[i]->Save();
  212. }
  213.  
  214. int
  215. TGroup::Map(int x)
  216. {
  217.   // May have to re-validate <x>
  218.   //
  219.   if (x == MapAsBefore)
  220.     x = scrollPos;
  221.   if (x > Items.GetItemsInContainer() || x == MapToBottom)
  222.     x = Items.GetItemsInContainer() - Windows.GetItemsInContainer();
  223.   if (x < 0 || x == MapToTop)
  224.     x = 0;
  225.   scrollPos = x;
  226.  
  227.   // Map each item to a window, as long as they fit
  228.   //
  229.   for (int i = 0; i < Windows.GetItemsInContainer(); i++, x++) {
  230.     if (x < Items.GetItemsInContainer()) {
  231.       *Windows[i] = *Items[x];
  232.       Windows[i]->EnableWindow(IsEnable());
  233.     } else
  234.       *Windows[i] = 0;      // No more item: "empty" the associated window
  235.   }
  236.   return scrollPos;
  237. }
  238.  
  239. int
  240. TGroup::UnMap()
  241. {
  242.   int i, x;
  243.   for (i = 0, x = scrollPos; i < Windows.GetItemsInContainer(); i++, x++) {
  244.     if (x < Items.GetItemsInContainer())
  245.       *Items[x] = *Windows[i];
  246.   }
  247.   return scrollPos;
  248. }
  249.  
  250.  
  251. //
  252. //  class TSysGroup
  253. //
  254.  
  255. TSysGroup::TSysGroup(TWindow *Dialog, int nID)
  256. {
  257.   // Create the child windows
  258.   //
  259.   for (int i = 0; Dialog->GetDlgItem(nID + i*4); i++)
  260.     Windows.Add(new TSysWindow(Dialog, nID + i*4));
  261.  
  262.   // Create the predefined system items (read from resources)
  263.   //
  264.   HRSRC hRes = GetApplicationObject()->FindResource(IDR_SYS_ITEMS, RT_RCDATA);
  265.   if (hRes) {
  266.     HGLOBAL hData = GetApplicationObject()->LoadResource(hRes);
  267.     if (hData) {
  268.       LPSTR pData = (LPSTR)::LockResource(hData);
  269.       // pData now points to a set of strings
  270.  
  271.       LPSTR pC = pData;
  272.       LPSTR pD;
  273.  
  274.       while(pC && *pC) {
  275.         char name[128];
  276.         char desc[128];
  277.         pD = pC + strlen(pC) + 2;
  278.         lstrcpy(name, pC);
  279.         lstrcpy(desc, pD);
  280.         Items.Add(new TSysItem(name, desc));
  281.         pC = pD + strlen(pD) + 2;
  282.       }
  283.       #if !defined(__WIN32__)
  284.         ::UnlockResource(hData);
  285.       #endif
  286.     }
  287.     #if !defined(__WIN32__)
  288.       ::FreeResource(hData);
  289.     #endif
  290.   }
  291.   // Load the values associated to each item
  292.   TGroup::Load();
  293. }
  294.  
  295. void
  296. TSysGroup::Cleanup()
  297. {
  298.   WritePrivateProfileString(SYS_CLS, 0, 0, SYS_INI);
  299.   WritePrivateProfileString(SYS_DSC, 0, 0, SYS_INI);
  300. }
  301.  
  302. //
  303. //  class TUsrGroup
  304. //
  305.  
  306. TUsrGroup::TUsrGroup(TWindow *Dialog, int nID)
  307. {
  308.   // Create the child windows
  309.   //
  310.   for (int i = 0; Dialog->GetDlgItem(nID + i*4); i++)
  311.     Windows.Add(new TUsrWindow(Dialog, nID + i*4));
  312.  
  313.   // Create the setup items (loaded from IniFile)
  314.   //
  315.   const int s = 4096;
  316.   char *p, *b = new char[s];
  317.   GetPrivateProfileString(USR_DSC, 0, "", b, s, USR_INI);
  318.   for (i = 0, p = b; p && *p; i++, p += strlen(p) + 1)
  319.     Items.Add(new TUsrItem(p));
  320.   delete b;
  321.  
  322.   // Load the values associated to each item
  323.   //
  324.   TGroup::Load();
  325. }
  326.  
  327. void
  328. TUsrGroup::Cleanup()
  329. {
  330. //  WritePrivateProfileString(USR_CLS, 0, 0, USR_INI);
  331.   WritePrivateProfileString(USR_DSC, 0, 0, USR_INI);
  332. }
  333.  
  334. //
  335. //  TSizableDialog makes a dialog sizable. Two sizes are defined: a small
  336. //  size and a large size. Call the Toggle function to switch to any size.
  337. //  To determine the size, define a dummy control in the dialog which
  338. //  provides the upper-right corner of the small size.
  339. //  TSizableDialog also know how to center itself accordingly to the parent
  340. //  window, and how to re-adjust its position after being centered, if gone
  341. //  out of view.
  342. //
  343.  
  344. void
  345. TSizableDialog::SetupWindow()
  346. {
  347.   TDialog::SetupWindow();
  348.   HWND hBox = GetDlgItem(nBoxID);
  349.   if (hBox) {
  350.     ::ShowWindow(hBox, SW_HIDE);
  351.     TRect rSmall, rLarge;
  352.     ::GetWindowRect(hBox, (LPRECT)&rSmall);
  353.     GetWindowRect(rLarge);
  354.     small.cx = rSmall.left - rLarge.left;
  355.     small.cy = rSmall.top - rLarge.top;
  356.     large = rLarge.Size();
  357.     tSize = t_max;
  358.     bMaximized = TRUE;
  359.  
  360.     // Tolerate some inaccuracy on the positionning of the small box...
  361.     //
  362.     if (abs(small.cx - large.cx) < 4)
  363.       small.cx = large.cx;
  364.     if (abs(small.cy - large.cy) < 4)
  365.       small.cy = large.cy;
  366.     Toggle(t_min);
  367.   }
  368.   Center();
  369. }
  370.  
  371. void
  372. TSizableDialog::Toggle(int tType)
  373. {
  374.   TSize newSize;
  375.   if (tType == t_minmax)
  376.     tType = (tSize == t_min) ? t_max : t_min;
  377.  
  378.   tSize = tType;
  379.   switch (tType) {
  380.     case t_min:
  381.       newSize = small;
  382.       break;
  383.     case t_max:
  384.       newSize = large;
  385.       break;
  386.     default:
  387.       return;
  388.   }
  389.   bMaximized = tType != t_max;
  390.   SetWindowPos(0, TRect(TPoint(0, 0), newSize), SWP_NOZORDER|SWP_NOMOVE);
  391. //  EnableControls();
  392. }
  393.  
  394. void
  395. TSizableDialog::EnableControls()
  396. {
  397.   TRect rParent = GetWindowRect();
  398.   HWND hChld = GetWindow(GW_CHILD);
  399.   while (hChld) {
  400.     POINT pt[2];
  401.     ::GetWindowRect(hChld, (RECT*)&pt);
  402.     if (!PtInRect(&rParent, pt[0]))
  403.       ::EnableWindow(hChld, 0);
  404.     hChld = ::GetWindow(hChld, GW_HWNDNEXT);
  405.   }
  406. }
  407.  
  408. void
  409. TSizableDialog::Center()
  410. {
  411.   TRect rPar;
  412.   TRect rDlg;
  413.   GetWindowRect(rDlg);
  414.   HWND hParent = GetParent();
  415.   if (!hParent)
  416.     hParent = GetDesktopWindow();
  417.   ::GetWindowRect(hParent, &rPar);
  418.  
  419.   int wDlgWidth = rDlg.Width();
  420.   int wDlgHeight = (rDlg.bottom - rDlg.top);
  421.  
  422.   int w = (rPar.right - rPar.left) - wDlgWidth;
  423.   int h = (rPar.bottom - rPar.top) - wDlgHeight;
  424.  
  425.   int x = rPar.left + (w / 2);
  426.   int y = rPar.top + (h / 2);
  427.  
  428.   MoveWindow(x, y, wDlgWidth , wDlgHeight, FALSE);
  429.   AdjustPos();
  430. }
  431.  
  432. void
  433. TSizableDialog::AdjustPos(void)
  434. {
  435.   int W = GetSystemMetrics(SM_CXSCREEN);
  436.   int H = GetSystemMetrics(SM_CYSCREEN);
  437.  
  438.   TRect r = GetWindowRect();
  439.   int w = r.Width();
  440.   int h = r.Height();
  441.  
  442.   if (r.left < 0)
  443.     r.left = 0;
  444.   if (r.top < 0)
  445.     r.top = 0;
  446.   if (r.right > W)
  447.     r.left = W - w;
  448.   if (r.bottom > H)
  449.     r.top -= (H - h);
  450.  
  451.   SetWindowPos(0, r.left, r.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  452. }
  453.  
  454.  
  455. //
  456. //  TGroupScroll provides the abstraction for a diagnostic group scrollbar.
  457. //  Associated to a diagnostic group, TGroupScroll simply map/unmap the
  458. //  diagnostic group on scroll events. It also knows how to hide itself when
  459. //  scrolling is irrelevant for that group (and show back if necessary):
  460.  
  461. DEFINE_RESPONSE_TABLE1(TGroupScroll, TScrollBar)
  462.   EV_WM_VSCROLL, 
  463. END_RESPONSE_TABLE;
  464.  
  465. TGroupScroll::TGroupScroll(TWindow* w, int i, TGroup* g)
  466.   : group(g), x(0), TScrollBar(w, i)
  467. {
  468.   Create();
  469.   Initialize(0);
  470. }
  471.  
  472. void
  473. TGroupScroll::Initialize(int pos)
  474. {
  475.   min = 0;
  476.   max = group->Items.GetItemsInContainer() - group->Windows.GetItemsInContainer();
  477.  
  478.   if (max <= min)
  479.     ShowWindow(SW_HIDE);    // Hide itself because scrolling is irrelevant
  480.  
  481.   else {
  482.     SetRange(min, max);
  483.     TScrollBar::SetPosition(x = pos);
  484.     EndScroll();
  485.     PageMagnitude = group->Windows.GetItemsInContainer() - 1;
  486.     ShowWindow(SW_SHOW);    // Show back itself, in case was previously hidden
  487.   }
  488. }
  489.  
  490. void
  491. TGroupScroll::EvVScroll(UINT code, UINT pos, HWND /*hCtl*/)
  492. {
  493.   switch (code) {
  494.     case SB_LINEDOWN:      if (x < max) SetPosition(x + LineMagnitude); break;
  495.     case SB_LINEUP:        if (x > min) SetPosition(x - LineMagnitude); break;
  496.     case SB_PAGEDOWN:      if (x < max) SetPosition(x + PageMagnitude); break;
  497.     case SB_PAGEUP:        if (x > min) SetPosition(x - PageMagnitude); break;
  498.     case SB_THUMBPOSITION: SetPosition(pos); break;
  499.     case SB_ENDSCROLL:     EndScroll(); break;
  500.   }
  501. }
  502.  
  503. void
  504. TGroupScroll::SetPosition(int pos)
  505. {
  506.   x = pos;
  507.   if (x < min) x = min;
  508.   if (x > max) x = max;
  509.   TScrollBar::SetPosition(x);
  510.  
  511.   // Perform the logical scroll by first unmaping the group and then
  512.   // by maping it to the new position:'
  513.   //
  514.   group->UnMap();
  515.   group->Map(x);
  516. }
  517.  
  518. void
  519. TGroupScroll::EndScroll()
  520. {
  521.   ::EnableScrollBar(*this, SB_CTL, ESB_ENABLE_BOTH);
  522.   if (x == min)
  523.     ::EnableScrollBar(*this, SB_CTL, ESB_DISABLE_LTUP);
  524.   if (x == max)
  525.     ::EnableScrollBar(*this, SB_CTL, ESB_DISABLE_RTDN);
  526.   if (::GetFocus()) {
  527.     ::InvalidateRect(::GetFocus(), 0, TRUE);
  528.     ::UpdateWindow(::GetFocus());
  529.   }
  530. }
  531.  
  532. //
  533. //  TSetupDialog drives the setup diagnostic dialog box
  534. //
  535.  
  536. DEFINE_RESPONSE_TABLE1(TSetupDialog, TDialog)
  537.   EV_COMMAND(IDC_MORE, CmZoom), 
  538.   EV_COMMAND(IDOK, CmOk), 
  539.   EV_COMMAND(IDC_ADD, CmAddUsr), 
  540.   EV_COMMAND(IDC_DEL, CmDelUsr), 
  541.   EV_COMMAND(IDC_EDT, CmEdtUsr), 
  542. END_RESPONSE_TABLE;
  543.  
  544. void
  545. TSetupDialog::SetupWindow()
  546. {
  547.   TSizableDialog::SetupWindow();
  548.  
  549.   // Create the two groups:
  550.   //
  551.   SysGroup = new TSysGroup(this, ID_SYS_CHECK);
  552.   UsrGroup = new TUsrGroup(this, ID_USR_CHECK);
  553.  
  554.   // Create the master enable switch and make it known to each group:
  555.   //
  556.   MainEnable = new TMainEnable(this, ID_SYS_ENABLE, SysGroup, UsrGroup);
  557.   SysGroup->SetMainSwitch(MainEnable);
  558.   UsrGroup->SetMainSwitch(MainEnable);
  559.  
  560.   // Map each group to the first position:
  561.   //
  562.   SysGroup->Map(0);
  563.   UsrGroup->Map(0);
  564.  
  565.   // Create the two group scrollbars and attach them to their groups:
  566.   //
  567.   SysScroll = new TGroupScroll(this, IDC_SYS_SCROLL, SysGroup);
  568.   UsrScroll = new TGroupScroll(this, IDC_USR_SCROLL, UsrGroup);
  569.  
  570.   // Finally, create the actions buttons and update their enable states:
  571.   //
  572.   pDel = new TButton(this, IDC_DEL);
  573.   pDel->Create();
  574.   pEdt = new TButton(this, IDC_EDT);
  575.   pEdt->Create();
  576.   UpdateButtons();
  577. }
  578.  
  579. void
  580. TSetupDialog::CleanupWindow()
  581. {
  582.   // Delete everybody
  583.   //
  584.   delete MainEnable;
  585.   delete UsrScroll;
  586.   delete SysScroll;
  587.   delete SysGroup;
  588.   delete UsrGroup;
  589.   delete pDel;
  590.   delete pEdt;
  591. }
  592.  
  593. void
  594. TSetupDialog::CmZoom()
  595. {
  596.   // The uses clicked on the <More/Less> button: resize the dialog box
  597.   // and update the button title accordingly:
  598.   //
  599.   Toggle(TSizableDialog::t_minmax);
  600.   SetDlgItemText(IDC_MORE, !IsMaximized()? "<<< &Less" : "&More >>>");
  601. }
  602.  
  603. void
  604. TSetupDialog::CmOk()
  605. {
  606.   // The user validated the changes: unmap to get the physical states and
  607.   // save each group:
  608.   //
  609.   SysGroup->UnMap();
  610.   UsrGroup->UnMap();
  611.   SysGroup->Save();
  612.   UsrGroup->Save();
  613.   MainEnable->Save();
  614.   TSizableDialog::CmOk();
  615. }
  616.  
  617. void
  618. TSetupDialog::CmAddUsr()
  619. {
  620.   // The user selected the 'Add User Group' command. Execute the AddUser
  621.   // dialog box
  622.   //
  623.   TAddUsrDialog Dialog(this);
  624.   if (Dialog.Execute() == IDOK) {
  625.     // Unmap the user group to not lose the last changes, append
  626.     // the new user group to the end of the group and map the group
  627.     // by positionning to the bottom:
  628.     //
  629.     UsrGroup->UnMap();
  630.     UsrGroup->Items.Add(new TUsrItem(Dialog.Class, Dialog.Descr));
  631.  
  632.     int x = UsrGroup->Map(TGroup::MapToBottom);
  633.  
  634.     // Don't forget to reset the scrollbar:
  635.     //
  636.     if (UsrScroll)
  637.       UsrScroll->Initialize(x);
  638.   }
  639.   UpdateButtons();
  640. }
  641.  
  642. void
  643. TSetupDialog::CmDelUsr()
  644. {
  645.   // The user selected the 'Delete User Group' command. Execute the DelUser
  646.   // dialog box
  647.   //
  648.   TDelUsrDialog Dialog(this, &UsrGroup->Items);
  649.   if (Dialog.Execute() == IDOK) {
  650.     // Unmap the user group to not lose the last changes, delete
  651.     // the chosen user group re-map the group:
  652.     //
  653.     int x = UsrGroup->UnMap();
  654.     UsrGroup->Items.Detach(Dialog.nSel);
  655.     x = UsrGroup->Map(x - 1);
  656.  
  657.     // Don't forget to reset the scrollbar:
  658.     //
  659.     if (UsrScroll)
  660.       UsrScroll->Initialize(x);
  661.   }
  662.   UpdateButtons();
  663. }
  664.  
  665. void
  666. TSetupDialog::CmEdtUsr()
  667. {
  668.   // The user selected the 'Edit User Group' command. Execute the EdtUser
  669.   // dialog box
  670.   //
  671.   TEdtUsrDialog Dialog(this, &UsrGroup->Items);
  672.   if (Dialog.Execute() == IDOK) {
  673.     UsrGroup->Map(TGroup::MapAsBefore);
  674.   }
  675. }
  676.  
  677. void
  678. TSetupDialog::UpdateButtons()
  679. {
  680.   // Can only edit/delete not empty user group!
  681.   //
  682.   BOOL bEnable = UsrGroup->Items.GetItemsInContainer() > 0;
  683.   pDel->EnableWindow(bEnable);
  684.   pEdt->EnableWindow(bEnable);
  685. }
  686.  
  687. //
  688. //  TAddUsrDialog: Prompts the user for two informations - a diagnostic
  689. //  classname and a diagnostic description. Require the classname and
  690. //  defaults the description to the classname.
  691. //
  692.  
  693. DEFINE_RESPONSE_TABLE1(TAddUsrDialog, TDialog)
  694.   EV_COMMAND(IDOK, CmOk), 
  695. END_RESPONSE_TABLE;
  696.  
  697. void
  698. TAddUsrDialog::CmOk()
  699. {
  700.   ::GetWindowText(GetDlgItem(IDC_DESCR), Descr, sizeof(Descr));
  701.   ::GetWindowText(GetDlgItem(IDC_CLASS), Class, sizeof(Class));
  702.   if (!*Class) {
  703.     // Classname is required
  704.     //
  705.     MessageBox(
  706.       string(*GetModule(), IDS_ERR_ADD_TXT).c_str(), 
  707.       string(*GetModule(), IDS_ERR_ADD_CAP).c_str(), 
  708.       MB_OK|MB_ICONHAND);
  709.     ::SetFocus(GetDlgItem(IDC_CLASS));
  710.     return;
  711.   }
  712.   if (!*Descr)
  713.     // Defaults the description to the classname
  714.     //
  715.     strcpy(Descr, Class);
  716.  
  717.   // Put the template on the clipboard
  718.   //
  719.   CopyToClipboard(this, Descr, Class);
  720.  
  721.   TDialog::CmOk();
  722. }
  723.  
  724. //
  725. //  TItemsDialog: serves as a base class to the dialogs which need to
  726. //  show to the user a list of setup items. Know how to fill itself, 
  727. //  given an array of setup items.
  728. //
  729.  
  730. DEFINE_RESPONSE_TABLE1(TItemsDialog, TDialog)
  731.   EV_COMMAND(IDOK, CmOk), 
  732.   EV_LBN_DBLCLK(IDC_LIST, LBDblClk), 
  733.   EV_LBN_SELCHANGE(IDC_LIST, LBSelChange), 
  734. END_RESPONSE_TABLE;
  735.  
  736. void
  737. TItemsDialog::SetupWindow()
  738. {
  739.   CHECK(items != 0);
  740.   pList = new TListBox(this, IDC_LIST);
  741.   CHECK(pList != 0);
  742.   pList->Create();
  743.   for (int i = 0; i < items->GetItemsInContainer(); i++)
  744.     pList->AddString((*items)[i]->GetDescr());
  745. }
  746.  
  747. TItemsDialog::~TItemsDialog() { delete pList; }
  748.  
  749. //
  750. //  TDelUsrDialog: animates the 'Delete User Group' dialog box. Just have
  751. //  to do the error handling, the base class doing the rest:
  752. //
  753.  
  754. void
  755. TDelUsrDialog::CmOk()
  756. {
  757.   nSel = pList->GetSelIndex();
  758.   if (nSel == LB_ERR) {
  759.     MessageBox(
  760.       string(*GetModule(), IDS_ERR_DEL_TXT).c_str(), 
  761.       string(*GetModule(), IDS_ERR_DEL_CAP).c_str(), 
  762.       MB_OK|MB_ICONHAND);
  763.     ::SetFocus(*pList);
  764.   } else
  765.     TItemsDialog::CmOk();
  766. }
  767.  
  768. //
  769. //  TEdtUsrDialog: animates the 'edit User Group' dialog box. This enable
  770. //  the user to change classname/description of setup items after having
  771. //  created them. Also, generates on demand a C++ example on the clipboard:
  772. //
  773.  
  774.  
  775. DEFINE_RESPONSE_TABLE1(TEdtUsrDialog, TItemsDialog)
  776. END_RESPONSE_TABLE;
  777.  
  778. void
  779. TEdtUsrDialog::LBSelChange()
  780. {
  781.   if (nPrevSel != LB_ERR) {
  782.     char Class[40], Descr[40];
  783.     GetDlgItemText(IDC_DESCR, Descr, sizeof(Descr));
  784.     GetDlgItemText(IDC_CLASS, Class, sizeof(Class));
  785.     (*items)[nPrevSel]->SetDescr(Descr);
  786.     (*items)[nPrevSel]->SetClass(Class);
  787.     pList->SetItemData(nPrevSel, (DWORD)Descr);
  788.   }
  789.   if ((nPrevSel = nSel = pList->GetSelIndex()) != LB_ERR) {
  790.     SetDlgItemText(IDC_DESCR, (*items)[nSel]->GetDescr());
  791.     SetDlgItemText(IDC_CLASS, (*items)[nSel]->GetClass());
  792.   }
  793. }
  794.  
  795. void  
  796. TEdtUsrDialog::CmOk()
  797.   LBSelChange(); 
  798.  
  799.   char descr[40], className[40];
  800.  
  801.   GetDlgItemText(IDC_DESCR, descr, sizeof(descr));
  802.   GetDlgItemText(IDC_CLASS, className, sizeof(className));
  803.   CopyToClipboard(this, descr, className);
  804.  
  805.   TItemsDialog::CmOk(); 
  806. }
  807.