home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / OWLSRC.PAK / STATUSBA.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  10.9 KB  |  436 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1992, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.18  $
  6. //
  7. // Implementation of TStatusBar
  8. //----------------------------------------------------------------------------
  9. #include <owl/pch.h>
  10. #if !defined(OWL_STATUSBA_H)
  11. # include <owl/statusba.h>
  12. #endif
  13. #if !defined(OWL_MODEGAD_H)
  14. # include <owl/modegad.h>
  15. #endif
  16. #if !defined(WINSYS_UIMETRIC_H)
  17. # include <winsys/uimetric.h>
  18. #endif
  19. #if !defined(OWL_STATUSBA_RH)
  20. # include <owl/statusba.rh>
  21. #endif
  22.  
  23. OWL_DIAGINFO;
  24.  
  25. //
  26. // Local class to manage the mode indicator strings
  27. //
  28. class TModeStrings {
  29.   public:
  30.     // Constructor
  31.     //
  32.     TModeStrings() : ModeBuff(0), ModeStrings(0), NumModes(0) {}
  33.    ~TModeStrings()
  34.     {
  35.       delete[] ModeBuff;
  36.       delete[] ModeStrings;
  37.     }
  38.  
  39.     void Init(TModule* module, uint16 resId, const char* defaultModes);
  40.  
  41.     // Accessors
  42.     int          Count() const            { return NumModes; }
  43.     const char*  operator [](int i) const { return ModeStrings[i]; }
  44.  
  45.   private:
  46.     int    NumModes;
  47.     char*  ModeBuff;
  48.     char** ModeStrings;
  49. };
  50.  
  51. //
  52. // Gets the mode string array from a single resource string, like:
  53. //   "EXT|CAPS|NUM|SCRL|OVR|REC"
  54. // using the provided default string if resource not found.
  55. //
  56. void
  57. TModeStrings::Init(TModule* module, uint16 resId, const char* defaultModes)
  58. {
  59.   if (!ModeStrings) {
  60.     string modeResString(module->LoadString(resId));
  61.     ModeBuff = strnewdup(modeResString.length() > 0 ?
  62.                          modeResString.c_str() :
  63.                          defaultModes);
  64.     NumModes = 1;
  65.     for (TCharIterator<char> i(ModeBuff); ; i++) {
  66.       if (!*i.Current())
  67.         break;
  68.       if (*i.Current() == '|') {
  69.         *i.Current() = 0;
  70.         NumModes++;
  71.       }
  72.     }
  73.  
  74.     typedef char* pchar;
  75.     ModeStrings = new pchar[NumModes];
  76.     char* p = ModeBuff;
  77.     for (int j = 0; j < NumModes; j++) {
  78.       ModeStrings[j] = p;
  79.       p += strlen(p) + 1;
  80.     }
  81.   }
  82. }
  83.  
  84. //
  85. // Static mode string object, & default mode indicator strings
  86. //
  87. static char  DefOnModes[] =  "EXT|CAPS|NUM|SCRL|OVR|REC";
  88. static TModeStrings&
  89. GetModeOnStrings()
  90. {
  91.   static TModeStrings ModeOnStrings;
  92.   return ModeOnStrings;
  93. }
  94.  
  95. static int VkKeys[] = {
  96.   0,
  97.   VK_CAPITAL,
  98.   VK_NUMLOCK,
  99.   VK_SCROLL,
  100.   VK_INSERT,
  101.   0
  102. };
  103.  
  104. static int GadgetIds[] = {
  105.   IDG_STATUS_EXT,
  106.   IDG_STATUS_CAPS,
  107.   IDG_STATUS_NUM,
  108.   IDG_STATUS_SCRL,
  109.   IDG_STATUS_OVR,
  110.   IDG_STATUS_REC
  111. };
  112.  
  113. //----------------------------------------------------------------------------
  114.  
  115. IMPLEMENT_CASTABLE(TStatusBar);
  116.  
  117. #if !defined(BI_PLAT_WIN16)
  118. DEFINE_RESPONSE_TABLE1(TStatusBar, TMessageBar)
  119.   EV_WM_NCHITTEST,
  120.   EV_OWLFRAMESIZE,
  121. END_RESPONSE_TABLE;
  122. #endif
  123.  
  124. //
  125. // Construct a status bar with a given style, font, etc.
  126. // borderStyle is used as the default for inserted gadgets.
  127. //
  128. TStatusBar::TStatusBar(TWindow*              parent,
  129.                        TGadget::TBorderStyle borderStyle,
  130.                        uint                  modeIndicators,
  131.                        TFont*                font,
  132.                        TModule*              module)
  133. :
  134.   TMessageBar(parent, font, module)
  135. {
  136.   BorderStyle = borderStyle;
  137.   ModeIndicators = modeIndicators;
  138.   ModeIndicatorState = 0;
  139.   NumModeIndicators = 0;
  140.   WideHintText = true;
  141.   GetModeOnStrings().Init(GetModule(), IDS_MODES, DefOnModes);
  142.  
  143.   // Statusbars should always stay flush to the decorated frame's border
  144.   //
  145.   SetFlag(wfInsertAtEdge);
  146.  
  147.   if (BorderStyle == TGadget::Plain || BorderStyle == TGadget::Embossed)
  148.     HighlightLine = false;
  149.   else
  150.     Spacing.Value = 2;  // Hilight line + 1/4-em margin on raised & recessed
  151.  
  152.   switch (BorderStyle) {
  153.     case TGadget::Raised:
  154.     case TGadget::Recessed:
  155.       // We want one border height along the top and bottom and 1/2 an em quad
  156.       // along the left and right so we will set pixels and compute the lengths
  157.       // ourselves
  158.       //
  159.       Margins.Units = TMargins::Pixels;
  160.       Margins.Left  = LayoutUnitsToPixels(4);
  161.       Margins.Right = LayoutUnitsToPixels(4);
  162.  
  163.     
  164. #if !defined(BI_PLAT_WIN16)
  165.       // The UI for a sizegrip isn't available in 16-bit Windows
  166.       //
  167.       if (ModeIndicators & SizeGrip)
  168.         Margins.Right = LayoutUnitsToPixels(1);
  169. #endif
  170.       Margins.Top = Margins.Bottom = TUIMetric::CyBorder;
  171.       break;
  172.  
  173.     case TGadget::Plain:
  174.       Margins.Units = TMargins::BorderUnits;
  175.       Margins.Left = Margins.Top = Margins.Right = Margins.Bottom = -1;
  176.       break;
  177.   }
  178.  
  179.   Gadgets->SetBorderStyle(BorderStyle); // Set border style for first gadget
  180.  
  181.   // Create text gadgets for any mode indicators the user requested,
  182.   // using provided border style.
  183.   //
  184.   TScreenDC   dc;
  185.   dc.SelectObject(*Font);
  186.  
  187.   for (int i = 0; i < GetModeOnStrings().Count(); i++)
  188.     if (ModeIndicators & (1 << i)) {
  189.       TTextGadget* gadget;
  190.       if (::VkKeys[i] == 0) {
  191.         gadget = new TTextGadget(GadgetIds[i], BorderStyle, TTextGadget::Left,
  192.                                  lstrlen(GetModeOnStrings()[i]), 
  193.                                  GetModeOnStrings()[i], 0);
  194.         gadget->SetEnabled(false);
  195.       }
  196.       else
  197.         gadget = new TModeGadget(VkKeys[i], GetModeOnStrings()[i], 
  198.                                  GadgetIds[i],
  199.                                  BorderStyle, TModeGadget::Center, 0);
  200.  
  201.       TMargins margins = gadget->GetMargins();
  202.  
  203.       // Use small left and right margins
  204.       //
  205.       margins.Left = margins.Right = 2;
  206.       gadget->SetMargins(margins);
  207.  
  208.       TMessageBar::Insert(*gadget);
  209.       NumModeIndicators++;
  210.     }
  211.  
  212. #if !defined(BI_PLAT_WIN16)
  213.   if (ModeIndicators & SizeGrip) {
  214.     InsertSizeGrip();
  215.   }
  216. #endif
  217.  
  218. }
  219.  
  220. #if !defined(BI_PLAT_WIN16)
  221. //
  222. //  Create a size grip and place it on the status bar.
  223. //  (Size grips are not available on 16-bit Windows.)
  224. //
  225. void
  226. TStatusBar::InsertSizeGrip()
  227. {
  228.   PRECONDITION(
  229.     TYPESAFE_DOWNCAST(GadgetWithId(IDG_SIZEGRIP), TSizeGripGadget) == 0);
  230.  
  231.   TSizeGripGadget* gadget = new TSizeGripGadget;
  232.   TMessageBar::Insert(*gadget, TGadgetList::After);
  233.   TRect bounds = gadget->GetBounds();
  234.   bounds.Inflate(1, 1);
  235.   gadget->SetBounds(bounds);
  236.   NumModeIndicators++;
  237. }
  238. #endif
  239.  
  240. //
  241. // Determines if a given gadget is being used as a mode indicator
  242. //
  243. bool
  244. TStatusBar::IsModeIndicator(TGadget* gadget)
  245. {
  246.   int      nonModeIndicators = NumGadgets - NumModeIndicators;
  247.   TGadget* g = Gadgets;
  248.  
  249.   for (int i = 0; i < nonModeIndicators; i++) {
  250.     if (gadget == g)
  251.       return false;
  252.  
  253.     g = g->NextGadget();
  254.   }
  255.  
  256.   return true;
  257. }
  258.  
  259. //
  260. // Override TGadgetWindow's callback during tiling to tweak the spacing
  261. // around the mode indicators
  262. //
  263. void
  264. TStatusBar::PositionGadget(TGadget*, TGadget* next, TPoint& origin)
  265. {
  266.   int  cxBorder = TUIMetric::CxBorder;
  267.  
  268.   if (BorderStyle == TGadget::Plain)
  269.     origin.x -= cxBorder;  // overlap the borders
  270.  
  271. #if !defined(BI_PLAT_WIN16)
  272.   TSizeGripGadget* gadget = TYPESAFE_DOWNCAST(next, TSizeGripGadget);
  273.   if (gadget)
  274.     return;
  275. #endif
  276.  
  277.   // Leave extra spacing between the mode indicators
  278.   //
  279.   if (IsModeIndicator(next))
  280.     switch (Spacing.Units) {
  281.       case TMargins::Pixels:
  282.         origin.x += Spacing.Value;
  283.         break;
  284.  
  285.       case TMargins::LayoutUnits:
  286.         origin.x += LayoutUnitsToPixels(Spacing.Value);
  287.         break;
  288.  
  289.       case TMargins::BorderUnits:
  290.         origin.x += Spacing.Value * cxBorder;
  291.         break;
  292.     }
  293. }
  294.  
  295. //
  296. // Insert a gadget. Default placement is just after the gadget to the left of
  297. // the status mode indicators
  298. //
  299. void
  300. TStatusBar::Insert(TGadget& gadget, TPlacement placement, TGadget* sibling)
  301. {
  302.   gadget.SetBorderStyle(BorderStyle);
  303.   if (!sibling)
  304.     sibling = operator[](NumGadgets - NumModeIndicators - 1);
  305.   TMessageBar::Insert(gadget, placement, sibling);
  306. }
  307.  
  308. //
  309. // Overriden to allow hint text to be displayed in the text gadget
  310. //
  311. void    
  312. TStatusBar::SetHintText(const char* text) 
  313. {
  314.   if (WideHintText)
  315.     // This displays hint that covers the whole gadget window
  316.     //
  317.     TMessageBar::SetHintText(text);
  318.   else
  319.     // This displays the text in the text gadget.
  320.     //
  321.     SetText(text);
  322. }
  323.  
  324. //
  325. // Get the text gadget & the mode string associated with a mode indicator
  326. //
  327. bool
  328. TStatusBar::GetGadgetAndStrings(TModeIndicator mode, TTextGadget*& gadget,
  329.                                 const char*& strOn)
  330. {
  331.   if ((ModeIndicators & mode) == 0) {
  332.     return false;  // tracing
  333.   }
  334.   else {
  335.     uint  slot = NumGadgets - 1;
  336.     int   index;
  337.  
  338.     for (index = GetModeOnStrings().Count() - 1; (1 << index) > mode; index--)
  339.       if (ModeIndicators & (1 << index))
  340.         slot--;
  341.  
  342.     strOn  = GetModeOnStrings()[index];
  343.  
  344.     for (gadget = (TTextGadget*)Gadgets; slot > 0; slot--)
  345.       gadget = (TTextGadget*)gadget->NextGadget();
  346.  
  347.     return true;
  348.   }
  349. }
  350.  
  351. //
  352. // Toggle the state of a mode indicator gadget
  353. //
  354. void
  355. TStatusBar::ToggleModeIndicator(TModeIndicator mode)
  356. {
  357.   SetModeIndicator(mode, !GetModeIndicator(mode));
  358. }
  359.  
  360. //
  361. // Enable and disable mode indicators
  362. //
  363. void
  364. TStatusBar::SetModeIndicator(TModeIndicator mode, bool on)
  365. {
  366.   TTextGadget*  gadget;
  367.   const char*   strOn;
  368.  
  369.   if (GetGadgetAndStrings(mode, gadget, strOn)) {
  370.     gadget->SetEnabled(on);
  371.   }
  372.  
  373.   if (on)
  374.     ModeIndicatorState |= mode;
  375.   else
  376.     ModeIndicatorState &= ~mode;
  377. }
  378.  
  379. #if !defined(BI_PLAT_WIN16)
  380.  
  381. //
  382. // If the status bar has a size grip gadget and the mouse is over the gadget,
  383. // simulate resizing of the frame.
  384. //
  385. uint
  386. TStatusBar::EvNCHitTest(TPoint& point)
  387. {
  388.   uint retVal = TMessageBar::EvNCHitTest(point);
  389.  
  390.   TSizeGripGadget* grip = TYPESAFE_DOWNCAST(GadgetWithId(IDG_SIZEGRIP), TSizeGripGadget);
  391.   if (grip && grip->GetEnabled()) {
  392.     ScreenToClient(point);
  393.     TRect rect = grip->GetBounds();
  394.     rect.right += 1;
  395.     rect.bottom += 1;
  396.     if (rect.Contains(point))   
  397.       retVal = HTBOTTOMRIGHT;
  398.   }
  399.  
  400.   return retVal;
  401. }
  402.  
  403. //
  404. // If the frame window that owns the status bar maximizes,
  405. // then remove the size grip.  (Otherwise, the size grip
  406. // remains uselessly and confusingly active in a maximized window.)
  407. //
  408. void
  409. TStatusBar::EvOwlFrameSize(uint sizeType, TSize&)
  410. {
  411.   TSizeGripGadget* grip = TYPESAFE_DOWNCAST(GadgetWithId(IDG_SIZEGRIP),
  412.                                             TSizeGripGadget);
  413.  
  414.   // If the window was maximized and has a grip, then remove the grip.
  415.   //
  416.   if (sizeType==SIZE_MAXIMIZED) {
  417.     if (grip) {
  418.       Remove(*grip);
  419.       delete grip;
  420.       NumModeIndicators--;
  421.       LayoutSession();
  422.     }
  423.   }
  424.   // If the window was restored and if it is supposed to have a size grip
  425.   // but the grip isn't there, then provide a new grip.
  426.   //
  427.   else if (sizeType == SIZE_RESTORED) {
  428.     if (!grip && (GetModeIndicators() & SizeGrip)) {
  429.       InsertSizeGrip();
  430.       LayoutSession();
  431.     }
  432.   }
  433. }
  434.  
  435. #endif // !BI_PLAT_WIN16
  436.