home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Libraries / CModalProgress / CModalProgress.cp next >
Encoding:
Text File  |  1994-09-01  |  15.3 KB  |  574 lines  |  [TEXT/MMCC]

  1. //
  2. //    CModalProgress.cp
  3. //    
  4. //    This file contains the definition information for the CModalProgress class.
  5. //    This class provides an interface for displaying to the user, a visual 
  6. //    indication to the progress of a time intensive task.
  7. //
  8. //    History
  9. //    -------
  10. //    
  11. //    01/9/94        G. Heathcote    Created version 1.0
  12. //
  13. //    Version 1.0
  14. //    
  15. //    Copyright 1994 Alysoft Solutions. All rights reserved.
  16. //
  17.  
  18. #ifndef __QUICKDRAW__
  19. #include <Quickdraw.h>
  20. #endif
  21.  
  22. #include "CModalProgress.h"
  23.  
  24. // ---------------------------------------------------------------------------
  25. //        • Local Prototypes
  26. // ---------------------------------------------------------------------------
  27.  
  28. pascal void DrawBar(WindowPtr theWindow, short itemNumber) ;
  29. pascal void DrawButtonRect(WindowPtr theWindow, short itemNumber) ;
  30.  
  31.  
  32. // ---------------------------------------------------------------------------
  33. //        • CModalProgress
  34. // ---------------------------------------------------------------------------
  35.  
  36. CModalProgress::CModalProgress()
  37. {    
  38.     fDialog = NULL ;
  39.     fCurrentPercent = 0.0 ;
  40.     fStartStatePercent = 0.0 ;
  41.     fCurrentStateSpacePercent = 0.0 ;
  42.     fInfiniteDrawDelay = kDefaultInfiniteDrawDelay ;
  43.     fPercentText = fProgressBar = fInfiniteBar = false ;
  44.     fPercentTextItem = fProgressBarItem = fInfiniteBarItem = 0 ;
  45.     fPercentTextDeltaLimit = 1 ;
  46. }
  47.  
  48. // ---------------------------------------------------------------------------
  49. //        • ~CModalProgress
  50. // ---------------------------------------------------------------------------
  51. //    Destructor. Delete the dialog structure if it is still around
  52.  
  53. CModalProgress::~CModalProgress()
  54. {
  55.     if (fDialog)
  56.         DisposeDialog(fDialog) ;
  57. }
  58.  
  59. // ---------------------------------------------------------------------------
  60. //        • SetupDialog
  61. // ---------------------------------------------------------------------------
  62. //    Set the dialog parameters
  63.  
  64. short CModalProgress::SetupDialog(short dlgResId)
  65. {
  66.     short                        itemType ;
  67.     Handle                        theItem ;
  68.     Rect                        box ;
  69.     short                        err = noErr ;
  70.     
  71.     fDialog = GetNewDialog(dlgResId, NULL, (WindowPtr)-1L) ;
  72.     if (fDialog)
  73.     {
  74.         SetWRefCon((WindowPtr)fDialog, (long)this) ;
  75.         
  76.         GetDialogItem(fDialog, kDefaultButtonOutlineIndex, &itemType, &theItem, &box) ;
  77.         if (itemType == userItem)
  78.         {
  79.             SetDialogItem(fDialog, kDefaultButtonOutlineIndex, itemType, (Handle)&DrawButtonRect, &box) ;
  80.         }
  81.     }
  82.     else
  83.         err = ResError() ;
  84.     
  85.     return err ;
  86. }
  87.  
  88. // ---------------------------------------------------------------------------
  89. //        • SetProgressBar
  90. // ---------------------------------------------------------------------------
  91. //    Set parameters for using the standard progress bar
  92.  
  93. void CModalProgress::SetProgressBar(short dlgItem)
  94. {
  95.     short                        itemType ;
  96.     Handle                        theItem ;
  97.     Rect                        box ;
  98.  
  99.     GetDialogItem(fDialog, dlgItem, &itemType, &theItem, &box) ;
  100.     if (itemType == userItem)
  101.     {
  102.         fProgressBar = true ;
  103.         fProgressBarItem = dlgItem ;
  104.         SetDialogItem(fDialog, fProgressBarItem, itemType, (Handle)&DrawBar, &box) ;
  105.     }
  106.     else
  107.     {
  108.         fProgressBar = false ;
  109.         fProgressBarItem = 0 ;
  110.     }
  111. }
  112.  
  113. // ---------------------------------------------------------------------------
  114. //        • SetInfiniteBar
  115. // ---------------------------------------------------------------------------
  116. //    Set parameters for using the infinite progress bar
  117.  
  118. void CModalProgress::SetInfiniteBar(short dlgItem)
  119. {
  120.     short                        itemType ;
  121.     Handle                        theItem ;
  122.     Rect                        box ;
  123.  
  124.     GetDialogItem(fDialog, dlgItem, &itemType, &theItem, &box) ;
  125.     if (itemType == userItem)
  126.     {
  127.         fInfiniteBar = true ;
  128.         fInfiniteBarItem = dlgItem ;
  129.         SetDialogItem(fDialog, fInfiniteBarItem, itemType, (Handle)&DrawBar, &box) ;
  130.     }
  131.     else
  132.     {
  133.         fInfiniteBar = false ;
  134.         fInfiniteBarItem = 0 ;
  135.     }
  136. }
  137.  
  138. // ---------------------------------------------------------------------------
  139. //        • SetPercentText
  140. // ---------------------------------------------------------------------------
  141. //    Set parameters for using the textual percent indicator
  142.  
  143. void CModalProgress::SetPercentText(short dlgItem, short deltaLimit)
  144. {
  145.     short                        itemType ;
  146.     Handle                        theItem ;
  147.     Rect                        box ;
  148.  
  149.     GetDialogItem(fDialog, dlgItem, &itemType, &theItem, &box) ;
  150.     if ((theItem != NULL) && (itemType == statText))
  151.     {
  152.         fPercentText = true ;
  153.         fPercentTextItem = dlgItem ;
  154.         fPercentTextDeltaLimit = deltaLimit ;
  155.     }
  156.     else
  157.     {
  158.         fPercentText = false ;
  159.         fPercentTextItem = 0 ;
  160.         fPercentTextDeltaLimit = 0 ;
  161.     }
  162. }
  163.  
  164. // ---------------------------------------------------------------------------
  165. //        • UpdateProgressIndicator
  166. // ---------------------------------------------------------------------------
  167. //    Force a redraw of the progress indicator(s)
  168.  
  169. void CModalProgress::UpdateProgressIndicator(float newPercent)
  170. {
  171.     GrafPtr                        oldPort ;
  172.  
  173.     GetPort(&oldPort) ;
  174.     SetPort((GrafPtr)fDialog) ;
  175.     DrawProgressIndicator(newPercent, kIndicatorContent) ;
  176.     SetPort(oldPort) ;
  177. }
  178.  
  179. // ---------------------------------------------------------------------------
  180. //        • SetCurrentState
  181. // ---------------------------------------------------------------------------
  182. //    Set the current progress state
  183.  
  184. void CModalProgress::SetCurrentState(float statePercent)
  185. {
  186.  
  187.     fCurrentPercent = fStartStatePercent + fCurrentStateSpacePercent ;
  188.     UpdateProgressIndicator(fCurrentPercent) ;
  189.     fStartStatePercent = fCurrentPercent ;
  190.  
  191.     fCurrentStateSpacePercent = statePercent - fStartStatePercent ;
  192.     fCurrentStateSpace = 0 ;
  193.     fCurrentStateValue = 0 ;
  194. }
  195.  
  196. // ---------------------------------------------------------------------------
  197. //        • SetStateSpace
  198. // ---------------------------------------------------------------------------
  199. //    Set the resolution of the current state
  200.  
  201. void CModalProgress::SetStateSpace(float space)
  202. {
  203.     fCurrentStateSpace = space ;
  204. }
  205.  
  206. // ---------------------------------------------------------------------------
  207. //        • SetCurrentStateValue
  208. // ---------------------------------------------------------------------------
  209. //    Set the current position in this state
  210.  
  211. short CModalProgress::SetCurrentStateValue(float value)
  212. {
  213.     float                        currentPercent ;
  214.     
  215.     fCurrentStateValue = value ;
  216.     currentPercent = (fCurrentStateSpacePercent / fCurrentStateSpace) * fCurrentStateValue ;
  217.  
  218.     fCurrentPercent = currentPercent + fStartStatePercent ;
  219.     UpdateProgressIndicator(fCurrentPercent) ;
  220.     
  221.     if (fCurrentStateValue < fCurrentStateSpace)
  222.         return kStateSpaceWithinLimit ;
  223.     else
  224.         return kStateSpaceExceedingLimit ;
  225. }
  226.  
  227. // ---------------------------------------------------------------------------
  228. //        • BeginModal
  229. // ---------------------------------------------------------------------------
  230. //    Set the Modal Dialog process
  231.  
  232. void CModalProgress::BeginModal()
  233. {
  234.     fInfiniteDrawTime = TickCount() + fInfiniteDrawDelay ;
  235.     ShowWindow((WindowPtr)fDialog) ;
  236.     DrawDialog(fDialog) ;
  237. }
  238.  
  239. // ---------------------------------------------------------------------------
  240. //        • FlashButton
  241. // ---------------------------------------------------------------------------
  242. //    Flash the indicated button
  243.  
  244. Boolean CModalProgress::FlashButton(DialogPtr theDialog, short buttonIndex)
  245. {
  246.     Rect                        aRect ;
  247.     ControlHandle                theItem ;
  248.     short                        itemType ;
  249.     long                        delayTime ;
  250.     Boolean                        retVal = false ;
  251.     
  252.     GetDialogItem(theDialog, buttonIndex, &itemType, (Handle*)&theItem, &aRect) ;
  253.     if (itemType == (btnCtrl + ctrlItem))
  254.     {
  255.         if ((**theItem).contrlHilite != 255)   /* is it enabled ? */
  256.         {
  257.             HiliteControl(theItem, 1) ;
  258.             Delay(6, &delayTime) ;
  259.             HiliteControl(theItem, 0) ;
  260.             
  261.             retVal = true ;
  262.         }
  263.     }
  264.  
  265.     return retVal ;
  266. }
  267.  
  268. // ---------------------------------------------------------------------------
  269. //        • ProcessEvent
  270. // ---------------------------------------------------------------------------
  271. //    Process the event from ProcessModal()
  272.  
  273. short CModalProgress::ProcessEvent(EventRecord *theEvent)
  274. {
  275.     short                        retVal = kDialogContinues ;
  276.  
  277.     switch(theEvent->what)
  278.     {
  279.         case updateEvt:
  280.             BeginUpdate((WindowPtr)fDialog) ;
  281.             DrawDialog(fDialog) ;
  282.             EndUpdate((WindowPtr)fDialog) ;
  283.             break ;
  284.  
  285.         case mouseDown:
  286.             WindowPtr            theWindow ;
  287.             Rect                aRect ;
  288.             
  289.             if (FindWindow(theEvent->where, &theWindow) == inDrag)
  290.             {
  291.                 if (theWindow == (WindowPtr)fDialog)
  292.                 {
  293.                     aRect = qd.screenBits.bounds ;
  294.                     InsetRect(&aRect, -4, -4) ;
  295.                     DragWindow(theWindow, theEvent->where, &aRect) ;
  296.                 }
  297.             }
  298.             else
  299.             if (FindWindow(theEvent->where, &theWindow) == inContent)
  300.             {
  301.                 if (theWindow == (WindowPtr)fDialog)
  302.                 {
  303.                     ControlHandle                    control ;
  304.                     GrafPtr                            oldPort ;
  305.                     short                            itemType ;
  306.                     Rect                            box ;
  307.                     ControlHandle                    theItem ;
  308.                     
  309.                     GetPort(&oldPort) ;
  310.                     SetPort((GrafPtr)fDialog) ;
  311.                     GlobalToLocal(&theEvent->where) ;
  312.                     SetPort(oldPort) ;
  313.                     if (FindControl(theEvent->where, (WindowPtr)fDialog, &control))
  314.                     {
  315.                         if (TrackControl(control, theEvent->where, NULL))
  316.                         {
  317.                             GetDialogItem(fDialog, ok, &itemType, (Handle*)&theItem, &box) ;
  318.                             if (control == theItem)
  319.                                 retVal = kDialogOKHit ;
  320.                             else
  321.                                 retVal = kDialogCancelHit ;
  322.                         }
  323.                     }
  324.                 }
  325.             }
  326.             break ;
  327.         
  328.         case keyDown:
  329.             short                keyCode ;
  330.  
  331.             keyCode = BitAnd(theEvent->message, charCodeMask) ;
  332.             switch (keyCode)
  333.             {
  334.                 case 46:    /* . */
  335.                     if ((theEvent->modifiers & cmdKey) != cmdKey)
  336.                         break ;
  337.                 
  338.                 case 27:    /* Escape */
  339.                     if (FlashButton(fDialog, cancel))
  340.                         retVal = kDialogCancelHit ;
  341.                     break ;
  342.                 
  343.                 case 13:    /* CR */
  344.                 case 3:        /* ENTER */
  345.                     if (FlashButton(fDialog, ok))
  346.                         retVal = kDialogOKHit ;
  347.                     break ;
  348.             }
  349.             break ;
  350.     }
  351.     
  352.     return retVal ;
  353. }
  354.  
  355.  
  356. // ---------------------------------------------------------------------------
  357. //        • ProcessModal
  358. // ---------------------------------------------------------------------------
  359. //    Do the general dialog processing
  360.  
  361. short CModalProgress::ProcessModal()
  362. {
  363.     EventRecord                    theEvent ;
  364.     Boolean                        ok ;
  365.     short                        retVal = kDialogContinues ;
  366.  
  367.     if (fInfiniteBar)
  368.     {
  369.         if (TickCount() > fInfiniteDrawTime)
  370.             UpdateProgressIndicator(fCurrentPercent) ;
  371.     }
  372.  
  373.     ok = GetNextEvent(everyEvent, &theEvent) ;
  374.     if (ok)
  375.     {
  376.         retVal = ProcessEvent(&theEvent) ;
  377.     }
  378.     
  379.     if ((fCurrentPercent >= 100) && (retVal == kDialogContinues))
  380.         retVal = kDialogExceeding100pc ;
  381.  
  382.     return retVal ;
  383. }
  384.  
  385. // ---------------------------------------------------------------------------
  386. //        • EndModal
  387. // ---------------------------------------------------------------------------
  388. //    Finished with the modal dialog
  389.  
  390. void CModalProgress::EndModal()
  391. {
  392.     FlushEvents(everyEvent, everyEvent) ;
  393.     HideWindow((WindowPtr)fDialog) ;
  394. }
  395.  
  396. // ---------------------------------------------------------------------------
  397. //        • DrawProgressIndicator
  398. // ---------------------------------------------------------------------------
  399. //    Draw the appropriate dialog items
  400.  
  401. void CModalProgress::DrawProgressIndicator(float percent, short part)
  402. {
  403.     if (fPercentText)
  404.         DrawPercentIndicator(percent, fPercentTextDeltaLimit, fPercentTextItem, part) ;
  405.     
  406.     if (fProgressBar)
  407.         DrawStdBarIndicator(percent, fProgressBarItem, part) ;
  408.     
  409.     if (fInfiniteBar)
  410.     {
  411.         if ((part & kIndicatorOutline) == kIndicatorOutline)
  412.             DrawInfiniteBarIndicator(percent, fInfiniteBarItem, part) ;
  413.         else
  414.         if (TickCount() > fInfiniteDrawTime)
  415.         {
  416.             fInfiniteDrawTime = TickCount() + fInfiniteDrawDelay ;
  417.             DrawInfiniteBarIndicator(percent, fInfiniteBarItem, part) ;
  418.         }
  419.     }
  420. }
  421.  
  422. // ---------------------------------------------------------------------------
  423. //        • DrawPercentIndicator
  424. // ---------------------------------------------------------------------------
  425.  
  426. void CModalProgress::DrawPercentIndicator(float percent, short deltaLimit, short itemIndex, short part)
  427. {
  428.     short                            itemType ;
  429.     Handle                            item ;
  430.     Rect                            box ;
  431.     Str255                            theText ;
  432.     long                            theNum ;
  433.     long                            percentLong ;
  434.     
  435.     GetDialogItem(fDialog, itemIndex, &itemType, &item, &box) ;
  436.     
  437.     GetIText(item, theText) ;
  438.     StringToNum(theText, &theNum) ;
  439.     percentLong = percent ;
  440.  
  441.     if (((percentLong - theNum) >= deltaLimit) &&
  442.         (percentLong > 0) )
  443.     {
  444.         NumToString(percentLong, theText) ;
  445.         SetIText(item, theText) ;
  446.     }
  447. }
  448.  
  449. // ---------------------------------------------------------------------------
  450. //        • DrawStdBarIndicator
  451. // ---------------------------------------------------------------------------
  452.  
  453. void CModalProgress::DrawStdBarIndicator(float percent, short itemIndex, short part)
  454. {
  455.     short                            itemType ;
  456.     Handle                            item ;
  457.     Rect                            box ;
  458.     static short                    previousRight = 0 ;
  459.     RGBColor                        barColor = {0x4444, 0x4444, 0x4444} ;
  460.     RGBColor                        emptyBarColor = {0xCCCC, 0xCCCC, 0xFFFF} ;
  461.     RGBColor                        currentForeColor ;
  462.     
  463.     GetDialogItem(fDialog, itemIndex, &itemType, &item, &box) ;
  464.     
  465.     //    Draw the frame of the progress indicator
  466.  
  467.     if ((part & kIndicatorOutline) == kIndicatorOutline)
  468.     {
  469.         //    Colour in the purple interior of the progress indicatorbar
  470.         
  471.         GetForeColor(¤tForeColor) ;
  472.         RGBForeColor(&emptyBarColor) ;
  473.         PaintRect(&box) ;
  474.         RGBForeColor(¤tForeColor) ;
  475.  
  476.         //    Draw the black frame around the outside
  477.         
  478.         FrameRect(&box) ;
  479.         previousRight = box.left + 1 ;        //    Ensure the entire body is drawn
  480.     }
  481.  
  482.     //    Draw the body of the progress indicator
  483.     
  484.     if ((part & kIndicatorContent) == kIndicatorContent)
  485.     {
  486.         InsetRect(&box, 1, 1) ;
  487.         box.right = box.left + ((float)(box.right - box.left) * (percent / 100.0)) ;
  488.         if (box.right > previousRight)
  489.         {
  490.             if (previousRight > 0)
  491.                 box.left = previousRight ;
  492.             previousRight = box.right ;
  493.             
  494.             GetForeColor(¤tForeColor) ;
  495.             RGBForeColor(&barColor) ;
  496.             PaintRect(&box) ;
  497.             RGBForeColor(¤tForeColor) ;
  498.         }
  499.     }
  500. }
  501.  
  502. // ---------------------------------------------------------------------------
  503. //        • DrawInfiniteBarIndicator
  504. // ---------------------------------------------------------------------------
  505.  
  506. void CModalProgress::DrawInfiniteBarIndicator(float percent, short itemIndex, short part)
  507. {
  508.     short                            itemType ;
  509.     Handle                            item ;
  510.     Rect                            box ;
  511.     static short                    originOffset = 0 ;
  512.     PixPatHandle                    thePattern ;
  513.     
  514.     GetDialogItem(fDialog, itemIndex, &itemType, &item, &box) ;
  515.  
  516.     //    Draw the outline of the progress indicator
  517.     
  518.     if ((part & kIndicatorOutline) == kIndicatorOutline)
  519.     {
  520.         FrameRect(&box) ;
  521.     }
  522.  
  523.     //    Draw the body of the indicator
  524.     
  525.     InsetRect(&box, 1, 1) ;
  526.     OffsetRect(&box, 0, originOffset) ;
  527.     thePattern = GetPixPat(kInfinitePaternResID) ;
  528.     PenPixPat(thePattern) ;
  529.     SetOrigin(0, originOffset) ;
  530.     PaintRect(&box) ;
  531.     
  532.     SetOrigin(0, 0) ;
  533.     PenNormal() ;
  534.  
  535.     //    Increment the origin offset if we have just been asked to draw the Content ONLY
  536.  
  537.     if (part == kIndicatorContent)
  538.         originOffset = (originOffset + 1) % ((((**(**thePattern).patMap).rowBytes) & 0xEFFF) * 8) ;
  539.  
  540.     DisposePixPat(thePattern) ;
  541. }
  542.  
  543.  
  544. // ---------------------------------------------------------------------------
  545. //        • Non-Class routines
  546. // ---------------------------------------------------------------------------
  547.  
  548. // ---------------------------------------------------------------------------
  549. //        • DawBar
  550. // ---------------------------------------------------------------------------
  551.  
  552. pascal void DrawBar(WindowPtr theWindow, short itemNumber)
  553. {
  554.     CModalProgress                    *theDialog ;
  555.     
  556.     theDialog = (CModalProgress*)GetWRefCon(theWindow) ;
  557.     theDialog->DrawProgressIndicator(theDialog->fCurrentPercent, kIndicatorOutline | kIndicatorContent) ;
  558. }
  559.  
  560. // ---------------------------------------------------------------------------
  561. //        • DrawButtonRect
  562. // ---------------------------------------------------------------------------
  563.  
  564. pascal void DrawButtonRect(WindowPtr theWindow, short itemNumber)
  565. {
  566.     Rect                            theRect ;
  567.     short                            itemType ;
  568.     Handle                            theItem ;
  569.  
  570.     GetDialogItem((DialogPtr)theWindow, itemNumber, &itemType, &theItem, &theRect) ;
  571.     PenSize(3, 3) ;
  572.     FrameRoundRect(&theRect, 16, 16) ;
  573.     PenNormal() ;
  574. }