home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / STATUSBA.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  7.6 KB  |  297 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1992, 1993 by Borland International
  3. //   source\owl\statusba.cpp
  4. //   Defines class TStatusBar.
  5. //----------------------------------------------------------------------------
  6. #include <owl\owlpch.h>
  7. #include <owl\statusba.h>
  8. #include <owl\statusba.rc>
  9.  
  10. static char   DefModes[] = "EXT|CAPS|NUM|SCRL|OVR|REC";
  11. static char*  ModeBuff;
  12. static char** ModeStrings;
  13. static int    NumModes = 0;
  14.  
  15. //
  16. // Gets the mode string array from a single resource string, like:
  17. //   "EXT|CAPS|NUM|SCRL|OVR|REC"
  18. //
  19. static void
  20. GetModes(HINSTANCE hInstance)
  21. {
  22.   if (!ModeStrings) {
  23.     string modeResString(hInstance, IDS_MODES);
  24.     ModeBuff = strnewdup(modeResString.length() > 0 ?
  25.                          modeResString.c_str() :
  26.                          DefModes);
  27.     NumModes = 1;
  28.     for (char* p = ModeBuff; *p; p++)
  29.       if (*p == '|') {
  30.         *p = 0;
  31.         NumModes++;
  32.       }
  33.  
  34.     typedef char* pchar;
  35.     ModeStrings = new pchar[NumModes];
  36.     p = ModeBuff;
  37.     for (int i = 0; i < NumModes; i++) {
  38.       ModeStrings[i] = p;
  39.       p += strlen(p) + 1;
  40.     }
  41.   }
  42. }
  43.  
  44. IMPLEMENT_CASTABLE(TStatusBar);
  45.  
  46. TStatusBar::TStatusBar(TWindow*              parent,
  47.                        TGadget::TBorderStyle borderStyle,
  48.                        UINT                  modeIndicators,
  49.                        TFont*                font,
  50.                        TModule*              module)
  51.   : TMessageBar(parent, font, module)
  52. {
  53.   BorderStyle = borderStyle;
  54.   ModeIndicators = modeIndicators;
  55.   ModeIndicatorState = 0;
  56.   NumModeIndicators = 0;
  57.   ::GetModes(*GetModule());
  58.  
  59.   if (BorderStyle == TGadget::Plain || BorderStyle == TGadget::Embossed)
  60.     HighlightLine = FALSE;
  61.  
  62.   else
  63.     Spacing.Value = 2;  // 1/4 em quad
  64.  
  65.   switch (BorderStyle) {
  66.     case TGadget::Raised:
  67.     case TGadget::Recessed:
  68.       //
  69.       // we want one border height along the top and bottom and 1/2 an em quad
  70.       // along the left and right so we will set pixels and compute the lengths
  71.       // ourselves
  72.       //
  73.       Margins.Units = TMargins::Pixels;
  74.       Margins.Left = Margins.Right = LayoutUnitsToPixels(4);
  75.       Margins.Top = Margins.Bottom = GetSystemMetrics(SM_CYBORDER);
  76.       break;
  77.  
  78.     case TGadget::Plain:
  79.       Margins.Units = TMargins::BorderUnits;
  80.       Margins.Left = Margins.Top = Margins.Right = Margins.Bottom = -1;
  81.       break;
  82.   }
  83.  
  84.   Gadgets->SetBorderStyle(BorderStyle); // Set border style for first gadget
  85.  
  86.   //
  87.   // create text gadgets for any mode indicators the user requested
  88.   //
  89.   TScreenDC   dc;
  90.  
  91.   dc.SelectObject(*Font);
  92.  
  93.   for (int i = 0; i < NumModes; i++)
  94.     if (ModeIndicators & (1 << i)) {
  95.       const int    SMALL_MARGIN = 1;
  96.       TSize        extent;
  97.       int          left, top, right, bottom;
  98.       TTextGadget* gadget = new TTextGadget(0, BorderStyle,
  99.                                             TTextGadget::Left,
  100.                                             strlen(ModeStrings[i]));
  101.       TMargins     margins = gadget->GetMargins();
  102.  
  103.       //
  104.       // use small left and right margins
  105.       //
  106.       margins.Left = margins.Right = SMALL_MARGIN;
  107.       gadget->SetMargins(margins);
  108.  
  109.       //
  110.       // turn off shrink wrapping for the width and choose a width that is
  111.       // custom fit for the string
  112.       //
  113.       dc.GetTextExtent(ModeStrings[i], strlen(ModeStrings[i]), extent);
  114.       gadget->SetShrinkWrap(FALSE, TRUE);
  115.       TMessageBar::Insert(*gadget);
  116.       gadget->GetOuterSizes(left, right, top, bottom);
  117.       extent.cx += left + right;
  118.       gadget->SetSize(extent);
  119.  
  120.       NumModeIndicators++;
  121.     }
  122. }
  123.  
  124. BOOL
  125. TStatusBar::IsModeIndicator(TGadget* gadget)
  126. {
  127.   int      nonModeIndicators = NumGadgets - NumModeIndicators;
  128.   TGadget* g = Gadgets;
  129.  
  130.   for (int i = 0; i < nonModeIndicators; i++) {
  131.     if (gadget == g)
  132.       return FALSE;
  133.  
  134.     g = g->NextGadget();
  135.   }
  136.  
  137.   return TRUE;
  138. }
  139.  
  140. //
  141. //
  142. //
  143. void
  144. TStatusBar::PositionGadget(TGadget*, TGadget* next, TPoint& origin)
  145. {
  146.   int  cxBorder = GetSystemMetrics(SM_CXBORDER);
  147.  
  148.   if (BorderStyle == TGadget::Plain)
  149.     origin.x -= cxBorder;  // overlap the borders
  150.  
  151.   //
  152.   // leave extra spacing between the mode indicators
  153.   //
  154.   if (IsModeIndicator(next))
  155.     switch (Spacing.Units) {
  156.       case TMargins::Pixels:
  157.         origin.x += Spacing.Value;
  158.         break;
  159.  
  160.       case TMargins::LayoutUnits:
  161.         origin.x += LayoutUnitsToPixels(Spacing.Value);
  162.         break;
  163.  
  164.       case TMargins::BorderUnits:
  165.         origin.x += Spacing.Value * cxBorder;
  166.         break;
  167.     }
  168. }
  169.  
  170. //
  171. // insert a gadget. default placement is just after the gadget to the left of
  172. // the status mode indicators
  173. //
  174. void
  175. TStatusBar::Insert(TGadget& gadget, TPlacement placement, TGadget* sibling)
  176. {
  177.   gadget.SetBorderStyle(BorderStyle);
  178.   if (!sibling)
  179.     sibling = operator[](NumGadgets - NumModeIndicators - 1);
  180.   TMessageBar::Insert(gadget, placement, sibling);
  181. }
  182.  
  183. //
  184. // return gadget at a given index, except mode indicator gadgets
  185. //
  186. TGadget*
  187. TStatusBar::operator [](UINT index)
  188. {
  189.   PRECONDITION(index < NumGadgets - NumModeIndicators);
  190.  
  191.   for (TGadget* g = Gadgets; index > 0; index--)
  192.     g = g->NextGadget();
  193.  
  194.   return g;
  195. }
  196.  
  197. //
  198. // Get the text gadget & the mode string associated with a mode indicator 
  199. //
  200. BOOL
  201. TStatusBar::GetGadgetAndString(TModeIndicator mode, TTextGadget*& gadget, char*& str)
  202. {
  203.   if ((ModeIndicators & mode) == 0) {
  204.     return FALSE;  // tracing
  205.  
  206.   } else {
  207.     UINT  slot = NumGadgets - 1;
  208.  
  209.     for (int index = NumModes - 1; (1 << index) > mode; index--)
  210.       if (ModeIndicators & (1 << index))
  211.         slot--;
  212.  
  213.     str = ModeStrings[index];
  214.  
  215.     for (gadget = (TTextGadget*)Gadgets; slot > 0; slot--)
  216.       gadget = (TTextGadget*)gadget->NextGadget();
  217.  
  218.     return TRUE;
  219.   }
  220. }
  221.  
  222. void
  223. TStatusBar::ToggleModeIndicator(TModeIndicator mode)
  224. {
  225.   SetModeIndicator(mode, !GetModeIndicator(mode));
  226. }
  227.  
  228. void
  229. TStatusBar::SetModeIndicator(TModeIndicator mode, BOOL on)
  230. {
  231.   TTextGadget*  gadget;
  232.   char*         str;
  233.  
  234.   if (GetGadgetAndString(mode, gadget, str))
  235.     gadget->SetText(on ? str : 0);
  236.   
  237.   if (on)
  238.     ModeIndicatorState |= mode;
  239.   else
  240.     ModeIndicatorState &= ~mode;
  241. }
  242.  
  243. BOOL
  244. TStatusBar::PreProcessMsg(MSG& msg)
  245. {
  246.   if (msg.message == WM_KEYDOWN) {  
  247.  
  248.     switch (msg.wParam) {
  249.       case VK_SCROLL:
  250.         
  251.         if (ModeIndicators & ScrollLock) {
  252.           //ScrollLockModeChange();
  253.           ToggleModeIndicator(ScrollLock);
  254.         }
  255.         break;
  256.  
  257.       case VK_INSERT:
  258.         if (ModeIndicators & Overtype) {
  259.           //OvertypeModeChange();
  260.           ToggleModeIndicator(Overtype);
  261.         }
  262.         break;
  263.  
  264.       case VK_CAPITAL:
  265.         if (ModeIndicators & CapsLock)
  266.           ToggleModeIndicator(CapsLock);
  267.         break;
  268.  
  269.       case VK_NUMLOCK:
  270.         if (ModeIndicators & NumLock)
  271.           ToggleModeIndicator(NumLock);
  272.         break;
  273.     }
  274.   }
  275.   
  276.   return FALSE;
  277. }
  278.  
  279. //
  280. //  Make sure that we are in sync with the physical KB indicators
  281. //
  282. BOOL
  283. TStatusBar::IdleAction(long idleCount)
  284. {
  285.   if (idleCount == 0) {
  286.     if ((::GetKeyState(VK_SCROLL) & 0x0001) != GetModeIndicator(ScrollLock))
  287.       ToggleModeIndicator(ScrollLock);
  288.     if ((::GetKeyState(VK_INSERT) & 0x0001) != !GetModeIndicator(Overtype))
  289.       ToggleModeIndicator(Overtype);
  290.     if ((::GetKeyState(VK_CAPITAL) & 0x0001) != GetModeIndicator(CapsLock))
  291.       ToggleModeIndicator(CapsLock);
  292.     if ((::GetKeyState(VK_NUMLOCK) & 0x0001) != GetModeIndicator(NumLock))
  293.       ToggleModeIndicator(NumLock);
  294.   }
  295.   return TMessageBar::IdleAction(idleCount);
  296. }
  297.