home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / PowerPlant / Slider / Slider.cp next >
Encoding:
Text File  |  1996-01-03  |  27.2 KB  |  915 lines  |  [TEXT/CWIE]

  1. // 
  2. // ===========================================================================
  3. //     Slider.cp                        ©1994 Scott Squires  
  4. // ===========================================================================
  5. //
  6.  
  7. /*
  8. HorzSlider and VertSlider are classes for PowerPlant that provide a movable
  9. slider similar to setting the volume control on the Mac.  I wrote these classes
  10. over a year ago with CW DR1 or 2.
  11.  
  12. Rather than dealing with CDEFs these classes can be compiled and used directly in
  13. your program and easily subclassed or modified for new behavior.  This makes
  14. tracking action very easy.
  15.  
  16. I'm posting this as freeware (but still copyrighted) for people to use as they
  17. like.
  18.  
  19. Scott Squires
  20.     Internet: squires@crl.com
  21.     AOL: ScottSquir 
  22.     CompuServe: 76545,573
  23.  
  24.  
  25. Usage:
  26.  
  27. Create a Base or background picture for your slider and save it as a PICT
  28. resource. Create a Slider picture for your slider and save it as a PICT resource.
  29. This should be smaller than your base picture.
  30.  
  31.  
  32. PPob Version:
  33.  
  34.     Using Window PPob with Slider built in:
  35.     
  36.     Create Window/view PPob with subviews of Hsld or Vsld.  You can do this in
  37.     PowerPlant Constructor by creating a view and changing it's type name to
  38.     Hsld or Vsld.
  39.     
  40.         // In App constructor register these classes
  41.         URegistrar::RegisterClass(HorzSlider::class_ID, HorzSlider::CreateHorzSliderStream);
  42.         URegistrar::RegisterClass(VertSlider::class_ID, VertSlider::CreateVertSliderStream);
  43.  
  44.         // after loading a PPob window with Sliders
  45.         HorzSlider * theSlider = (HorzSlider *)theView->FindPaneByID(2006);
  46.          theSlider->SetPicts(128,129);        // Pict ResID 128 is base
  47.                                              // Pict ResID 129 is slider
  48.         theSlider->SetMinMax(0,1000);        // sets value range
  49.          theSlider->SetValueMessage(2006);    // In your view listen for this msg
  50.  
  51.         if (theSlider->MakeSlider())        // Do the actual building of slider
  52.             theSlider->AddListener(theView);
  53.         else
  54.             delete theSlider;                    // delete if couldn't be created
  55.  
  56.  
  57.  
  58. Run Time Version:
  59.     // assumes you've created window and theView
  60.     HorzSlider *theSlider = new HorzSlider(128,129);    // Pict ResID 128 is base
  61.                                                         // Pict ResID 129 is slider
  62.     theSlider->PutInside(theView);
  63.      theSlider->SetMinMax(0,1000);        // sets value range
  64.       theSlider->SetValueMessage(2006);    // In your view listen for this msg
  65.  
  66.         if (theSlider->MakeSlider())    // Do the actual building of slider
  67.             theSlider->AddListener(theView);
  68.         else
  69.             delete theSlider;                    // delete if couldn't be created
  70.  
  71.  
  72.  
  73.  // In your view/listener do something like this:
  74.      void MyView::ListenToMessage(MessageT inMessage, void *ioParam)
  75.     {
  76.          switch (inMessage) {
  77.             // Message sent from Slider when value is updated
  78.              
  79.         case 2006:
  80.              NumToString(*(long *)ioParam, theNum);
  81.             SetRect(&box, 215, 10, 245, 30);
  82.             TextBox(theNum + 1, theNum[0], &box, teFlushRight);
  83.             break;
  84.     
  85.      }
  86.      }
  87.      
  88.      
  89.  
  90. Under the Hood:
  91.  
  92. Slider is an abstract class based on LView and LBroadcaster. HorzSlider and
  93. VertSlider are built from Slider.
  94.  
  95. When a slider object is created default values are set. During MakeSlider() the
  96. picture resources that were assigned are loaded and LGWorld objects are created
  97. to hold these pictures. If a third pict is specfied it is used as a selected
  98. slider. An additional LGWorld is created to hold the Slider image when it is
  99. updated.
  100.  
  101. The slider is resized to match the actual size of the base picture.
  102.  
  103. When a slider is clicked on the selected slider is displayed if one was
  104. specified.  The mouse is then tracked and the slider is continuously updated. For
  105. each update a Message is broadcast to any listeners with the new value.
  106.  
  107. DrawSelf() for the slider copies the GWorld with the base picture to the
  108. work GWorld.  The slider or selected slider is then copied to this as well.
  109. Finally the work GWorld is copied to the screen.
  110.  
  111.  
  112. Misc Notes:
  113.  
  114. Slider pictures are assumed to be smaller than the base pictures.
  115. Slider pictures can be offset within a base picture.
  116.  
  117. The Selected slider picture is assumed to be the same size as the normal slider.
  118. Sliders are dealt with as rectangular objects.  You can still simulate an
  119. irregular image.
  120.  
  121. Slider values are signed longs so can be quite large.
  122.  
  123. The LGWorlds are created with the deepest depth.  This allows the best speed for
  124. updates.  You could change this to 8 bits (256 colors) if memory will be tight.
  125.  
  126. If you click on the base picture and not the actual slider the slider will move
  127. instantly to that position.
  128.  
  129. Sliders have a flag that can cause the cursor to be hidden while tracking.
  130.  
  131. Sliders also have a flag that can just activate the slider, not the base picture.
  132.  
  133. Any window that Sliders are added to should be hidden until the MakeSlider() is
  134. executed.
  135.  
  136. MakeSlider() was factored out of the constructor to avoid memory problems in a
  137. constructor and to provide a little more flexibility.
  138.  
  139.  
  140. Future:
  141. Feel free to improve, subclass, or modify.
  142.  
  143. These are based on LView class to allow more flexibility but could be based on
  144. LPane without problems.
  145.  
  146. Rather than being based on LView these could be created from LControl with
  147. simularities to controls.  (min, max, values, etc)   
  148.  
  149. Slider PPobs are just LViews  renamed/typed.  As such the create from stream
  150. functions don't contain any more data than an LView would. Future versions of
  151. PowerPlant Constructor might make it easier to add the pict IDs and other values.
  152.  
  153. I had planned to implement 'dirty rectangles' to make the updates faster but that
  154. hasn't proved necessary for my uses.  This could be done by creating a function
  155. similar to DrawSelf that would be called while tracking.  Rather than copying the
  156. entire base GWorld over just the rectangle where the slider used to be would be
  157. copied to the temp GWorld.  The slider would be copied like usual and then the
  158. GWorld to window copy would only copy a rectangle that would cover the old and
  159. new slider rectangle.  (small if updated quickly)
  160.  
  161. Regions could be used for checking clicks and for copying irregular images.
  162. Create a temp GWorld 1 bit deep, draw slider pict and then use BitMapToRegion.
  163.  
  164. You could provide B&W and color picts and have correct versions loaded depending
  165. on screen depth.
  166.  
  167.  
  168. */
  169.  
  170. #include "Slider.h"
  171. #include <UGWorld.h>
  172. #include <PP_Messages.h>
  173.  
  174. // ---------------------------------------------------------------------------
  175. //        • SetDefaults
  176. // ---------------------------------------------------------------------------
  177. //    Init values in a slider
  178.  
  179.  
  180. void Slider::SetDefaults(void)
  181. {
  182.     mBasePictID = resID_Undefined;
  183.     mSliderPictID = resID_Undefined;
  184.     mSliderSelectPictID = resID_Undefined;
  185.     SetRect(&mBasePictRect, 0, 0, 100, 25);
  186.     SetRect(&mSliderRect, 0, 0, 25, 25);
  187.     mMinSliderValue = 0;
  188.     mMaxSliderValue = 100;
  189.     mSelected = false;
  190.     mSliderCursor = true;
  191.     mBaseGWorld = nil;
  192.     mSliderGWorld = nil;
  193.     mSliderSelectGWorld = nil;
  194.     mWorkGWorld = nil;
  195.     mSliderOnly = false;
  196.  
  197. }
  198.  
  199.  
  200. // ---------------------------------------------------------------------------
  201. //        • Slider
  202. // ---------------------------------------------------------------------------
  203. //    Default Constructor
  204.  
  205.  
  206. Slider::Slider()
  207. {
  208.     SetDefaults();
  209. }
  210.  
  211.  
  212. // ---------------------------------------------------------------------------
  213. //        • Slider(ResIDT mBasePictRes, ResIDT mSliderPictRes)
  214. // ---------------------------------------------------------------------------
  215. //     Create Slider and assign Pict resource numbers
  216.  
  217.  
  218. Slider::Slider(ResIDT BasePictRes, ResIDT SliderPictRes)
  219. {
  220.     SetDefaults();
  221.     mBasePictID = BasePictRes;
  222.     mSliderPictID = SliderPictRes;
  223.  
  224. }
  225.  
  226.  
  227. // ---------------------------------------------------------------------------
  228. //        • Slider(ResIDT mBasePictRes, ResIDT mSliderPictRes, ResIDT SlideSelectPictRes)
  229. // ---------------------------------------------------------------------------
  230. //     Create Slider including selected slider and assign Pict resource numbers
  231.  
  232.  
  233. Slider::Slider(ResIDT BasePictRes, ResIDT SliderPictRes, ResIDT SlideSelectPictRes)
  234. {
  235.     SetDefaults();
  236.     mBasePictID = BasePictRes;
  237.     mSliderPictID = SliderPictRes;
  238.     mSliderSelectPictID = SlideSelectPictRes;
  239.  }
  240.  
  241. // ---------------------------------------------------------------------------
  242. //        • Slider(LStream*)
  243. // ---------------------------------------------------------------------------
  244. //    Construct Slider from data in a Stream
  245.  
  246. Slider::Slider(LStream *inStream)
  247.     : LView(inStream)
  248.     {
  249.     SetDefaults();
  250.     }
  251.  
  252.  
  253. // ---------------------------------------------------------------------------
  254. //        • ~Slider
  255. // ---------------------------------------------------------------------------
  256. //    Destructor, deletes any LGWorld objects created
  257.  
  258.  
  259. Slider::~Slider(void)
  260. {
  261.     if (mBaseGWorld)
  262.         delete mBaseGWorld;
  263.     if (mWorkGWorld)
  264.         delete mWorkGWorld;
  265.     if (mSliderGWorld)
  266.         delete mSliderGWorld;
  267.     if (mSliderSelectGWorld)
  268.         delete mSliderSelectGWorld;
  269. }
  270.  
  271. // ---------------------------------------------------------------------------
  272. //        • MakeSlider
  273. // ---------------------------------------------------------------------------
  274. //    Loads PICT resources, creates LGWorlds, and draw pictures into LGWorlds
  275.  
  276. Boolean Slider::MakeSlider(void)
  277. {
  278.     PicHandle macPictureH = ::GetPicture(mBasePictID);
  279.     if (macPictureH != nil) {                         // Use PICT if found
  280.          mBasePictRect = (*macPictureH)->picFrame;
  281.         OffsetRect(&mBasePictRect, -mBasePictRect.left, -mBasePictRect.top);
  282.         mBaseLength = mBasePictRect.right;
  283.         mBaseHeight = mBasePictRect.bottom;
  284.                                                     // Adjust Pane size
  285.         ResizeFrameTo(mBasePictRect.right, mBasePictRect.bottom, false);
  286.  
  287.         mBaseGWorld = new LGWorld(mBasePictRect, 0, 0, 0, 0);        // Make GWorld
  288.  
  289.         if (mBaseGWorld) {                                // draw the picture
  290.             mBaseGWorld->BeginDrawing();
  291.             ::DrawPicture(macPictureH, &mBasePictRect);
  292.             mBaseGWorld->EndDrawing();
  293.  
  294.             mWorkGWorld = new LGWorld(mBasePictRect, 0, 0, 0, 0);
  295.  
  296.             if (mWorkGWorld) {
  297.                 mWorkGWorld->BeginDrawing();
  298.                 ::DrawPicture(macPictureH, &mBasePictRect);
  299.                 mWorkGWorld->EndDrawing();
  300.             }
  301.           }
  302.         ReleaseResource( (Handle)macPictureH ); 
  303.     }
  304.  
  305.     // Get Slider picture and make LGWorld
  306.     macPictureH = ::GetPicture(mSliderPictID);
  307.     if (macPictureH != nil) {
  308.          mSliderRect = (*macPictureH)->picFrame;
  309.         OffsetRect(&mSliderRect, -mSliderRect.left, -mSliderRect.top);
  310.         
  311.         mBaseLength = mBaseLength -  (mSliderRect.right - mSliderRect.left);
  312.         mBaseHeight = mBaseHeight -  (mSliderRect.bottom - mSliderRect.top);
  313.         mSliderGWorld = new LGWorld(mSliderRect, 0, 0, 0, 0);
  314.          if (mSliderGWorld) {
  315.             mSliderGWorld->BeginDrawing();
  316.             ::DrawPicture(macPictureH, &mSliderRect);
  317.             mSliderGWorld->EndDrawing();
  318.              
  319.         }
  320.         ReleaseResource( (Handle)macPictureH ); 
  321.     }
  322.  
  323.     if (mSliderSelectPictID != resID_Undefined)    // load and setup Selected pict if defined
  324.     {
  325.         macPictureH = ::GetPicture(mSliderSelectPictID);
  326.         if (macPictureH != nil) {
  327.  
  328.             mSliderSelectGWorld = new LGWorld(mSliderRect, 0, 0, 0, 0);
  329.              if (mSliderSelectGWorld) {
  330.                 mSliderSelectGWorld->BeginDrawing();
  331.                 ::DrawPicture(macPictureH, &mSliderRect);
  332.                 mSliderSelectGWorld->EndDrawing();
  333.             }
  334.              ReleaseResource( (Handle)macPictureH ); 
  335.         }
  336.  
  337.     }
  338.     // true if all needed picts found and GWorlds created
  339.       
  340.     return ((mBaseGWorld && mSliderGWorld && mWorkGWorld)
  341.       && ((mSliderSelectPictID == resID_Undefined) || mSliderSelectGWorld));
  342.      
  343.  
  344. }
  345.  
  346.  
  347. // ---------------------------------------------------------------------------
  348. //        • SetPicts
  349. // ---------------------------------------------------------------------------
  350. //    Defines PICT resource numbers for base and slider, no Selected slider
  351.  
  352. void Slider::SetPicts(ResIDT BasePictRes, ResIDT SliderPictRes)
  353. {
  354.     mBasePictID = BasePictRes;
  355.     mSliderPictID = SliderPictRes;
  356.  
  357. }
  358.  
  359. // ---------------------------------------------------------------------------
  360. //        • SetPicts
  361. // ---------------------------------------------------------------------------
  362. //    Defines PICT resource numbers for base, slider, and Selected slider
  363.  
  364. void Slider::SetPicts(ResIDT BasePictRes, ResIDT SliderPictRes, ResIDT SlideSelectPictRes)
  365. {
  366.  
  367.     mBasePictID = BasePictRes;
  368.     mSliderPictID = SliderPictRes;
  369.     mSliderSelectPictID = SlideSelectPictRes;
  370.  
  371. }
  372.  
  373.  
  374. // ---------------------------------------------------------------------------
  375. //        • OffsetSlider
  376. // ---------------------------------------------------------------------------
  377. //    Move Slider relative to base picture.  Used when slider is smaller tan base picture
  378.  
  379. void Slider::OffsetSlider(short Xoffset, short Yoffset)
  380. {
  381.     OffsetRect(&mSliderRect, Xoffset, Yoffset);
  382.  
  383. }
  384.  
  385.  
  386. // ---------------------------------------------------------------------------
  387. //        • DrawSelf
  388. // ---------------------------------------------------------------------------
  389. //    Draw the Slider
  390.  
  391. void Slider::DrawSelf()
  392. {
  393.     GrafPtr savePort;
  394.     GetPort(&savePort);
  395.     ::PenNormal();
  396.  
  397.     if (mBaseGWorld && mWorkGWorld) {
  398.         // copy base GWorld to temp GWorld
  399.  
  400.         mWorkGWorld->BeginDrawing();
  401.         mBaseGWorld->CopyImage((GrafPtr)mWorkGWorld->GetMacGWorld(), mBasePictRect, srcCopy, 0);
  402.         mWorkGWorld->EndDrawing();
  403.     }
  404.     if (mSelected && mSliderSelectGWorld)        // Is it selected and does a Select LGWorld exist?
  405.     {
  406.         if (mSliderSelectGWorld && mWorkGWorld) {
  407.             // copy Select slider GWorld to temp GWorld
  408.             mWorkGWorld->BeginDrawing();
  409.             mSliderSelectGWorld->CopyImage((GrafPtr)mWorkGWorld->GetMacGWorld(), mSliderRect, srcCopy, 0);
  410.             mWorkGWorld->EndDrawing();
  411.         }
  412.     } else {
  413.         if (mSliderGWorld && mWorkGWorld) {
  414.             // copy slider GWorld to temp GWorld
  415.             mWorkGWorld->BeginDrawing();
  416.             mSliderGWorld->CopyImage((GrafPtr)mWorkGWorld->GetMacGWorld(), mSliderRect, srcCopy, 0);
  417.             mWorkGWorld->EndDrawing();
  418.         }
  419.     }
  420.  
  421.     if (mWorkGWorld) {
  422.         mWorkGWorld->CopyImage(savePort, mBasePictRect, srcCopy, 0);// display it
  423.     } else {
  424.         FrameRect(&mBasePictRect);                // If all else fails, draw a box
  425.  
  426.     }
  427. }
  428.  
  429.  
  430. // ---------------------------------------------------------------------------
  431. //        • PointInSlider
  432. // ---------------------------------------------------------------------------
  433. //    Check to see if a point is within the slider rect
  434.  
  435. Boolean Slider::PointInSlider(Point thePoint)
  436. {
  437.     return (PtInRect(thePoint, &mSliderRect));
  438.  
  439. }
  440.  
  441.  
  442.  
  443.  
  444.  
  445. // ---------------------------------------------------------------------------
  446. //        • SetMinMax
  447. // ---------------------------------------------------------------------------
  448. //    Set min and max values for slider, long values
  449.  
  450. void Slider::SetMinMax(long theMin, long theMax)
  451. {
  452.     mMinSliderValue = theMin;
  453.     mMaxSliderValue = theMax;
  454.     if(IsVisible())
  455.     {
  456.         SetSliderValue(mValue);        // clamp existing value and redraw
  457.      }
  458. }
  459.  
  460.  
  461.  
  462.  
  463.  
  464. // ---------------------------------------------------------------------------
  465. //        • DoAction
  466. // ---------------------------------------------------------------------------
  467. //    Send message if new value
  468.  
  469. void Slider::DoAction(void)
  470. {
  471.     long tempValue;
  472.  
  473.     tempValue = GetSliderValue();
  474.     if (mValue != tempValue) {
  475.         // only send message if true value changed
  476.         mValue = tempValue;
  477.         BroadcastValueMessage();
  478.     }
  479.  
  480. }
  481.  
  482.  
  483. // ---------------------------------------------------------------------------
  484. //        • BroadcastValueMessage
  485. // ---------------------------------------------------------------------------
  486. //    Send message with value
  487.  
  488.  
  489. void Slider::BroadcastValueMessage()
  490. {
  491.     if (mValueMessage != cmd_Nothing) {
  492.         Int32 value = mValue;
  493.         BroadcastMessage(mValueMessage, (void *) & value);
  494.     }
  495. }
  496.  
  497.  
  498. // ---------------------------------------------------------------------------
  499. //        • SetValueMessage
  500. // ---------------------------------------------------------------------------
  501. //    Assign Message number
  502.  
  503. void Slider::SetValueMessage(MessageT inValueMessage)
  504. {
  505.     mValueMessage = inValueMessage;
  506. }
  507.  
  508.  
  509. // ---------------------------------------------------------------------------
  510. //        • GetValueMessage
  511. // ---------------------------------------------------------------------------
  512. //    Return Message number
  513.  
  514. MessageT Slider::GetValueMessage() const
  515. {
  516.     return mValueMessage;
  517. }
  518.  
  519.  
  520. // ---------------------------------------------------------------------------
  521. //        • SetCursorFlag
  522. // ---------------------------------------------------------------------------
  523. //    If true then display cursor, false hides cursor when tracking
  524.  
  525. void Slider::SetCursorFlag(Boolean theFlag)
  526. {
  527.     mSliderCursor = theFlag;
  528. }
  529.  
  530.  
  531. // ---------------------------------------------------------------------------
  532. //        • SetSliderOnlyFlag
  533. // ---------------------------------------------------------------------------
  534. //    If true then activate only when slider hit, false makes the whole base pciture active
  535.  
  536. void Slider::SetSliderOnlyFlag(Boolean theFlag)
  537. {
  538.     mSliderOnly = theFlag;
  539. }
  540.  
  541.  
  542. // ---------------------------------------------------------------------------
  543. //        • HorzSlider
  544. // ---------------------------------------------------------------------------
  545. //    Default Constructor
  546.  
  547. HorzSlider::HorzSlider()
  548.     : Slider()
  549.     {
  550.  
  551.     }
  552.  
  553. // ---------------------------------------------------------------------------
  554. //        • HorzSlider(ResIDT BasePictRes, ResIDT mSliderPictRes)
  555. // ---------------------------------------------------------------------------
  556. //     Create Horizontal Slider and assign Pict resource numbers
  557.  
  558. HorzSlider::HorzSlider(ResIDT BasePictRes, ResIDT SliderPictRes)
  559.     : Slider(BasePictRes, SliderPictRes)
  560.     {
  561.  
  562.     }
  563.  
  564.  
  565. // ---------------------------------------------------------------------------
  566. //        • HorzSlider(ResIDT BasePictRes, ResIDT mSliderPictRes, ResIDT SlideSelectPictRes))
  567. // ---------------------------------------------------------------------------
  568. //     Create Horizontal Slider and assign Pict resource numbers
  569.  
  570. HorzSlider::HorzSlider(ResIDT BasePictRes, ResIDT SliderPictRes, ResIDT SlideSelectPictRes)
  571.     : Slider(BasePictRes, SliderPictRes, SlideSelectPictRes)
  572.     {
  573.  
  574.     }
  575.  
  576.  
  577. // ---------------------------------------------------------------------------
  578. //        • HorzSlider(LStream*)
  579. // ---------------------------------------------------------------------------
  580. //    Construct HorzSlider from data in a Stream
  581.  
  582. HorzSlider::HorzSlider(LStream *inStream)
  583.     : Slider(inStream)
  584.     {
  585.  
  586.     }
  587.  
  588. // ---------------------------------------------------------------------------
  589. //        • CreateHorzSliderStream  [static]
  590. // ---------------------------------------------------------------------------
  591. //    Return a new HorzSlider object initialized using data from a Stream
  592.  
  593. HorzSlider *HorzSlider::CreateHorzSliderStream(LStream *inStream)
  594. {
  595.     return (new HorzSlider(inStream));
  596. }
  597.  
  598. // ---------------------------------------------------------------------------
  599. //        • ~HorzSlider
  600. // ---------------------------------------------------------------------------
  601. //    Destructor, deletes any LGWorld objects created
  602.  
  603. HorzSlider::~HorzSlider()
  604. {
  605.  
  606. }
  607.  
  608.  
  609. // ---------------------------------------------------------------------------
  610. //        • TrackSlider
  611. // ---------------------------------------------------------------------------
  612. //    Move slider while mouse button is down
  613. //  Calls DoAction() when moving
  614.  
  615.  
  616. void HorzSlider::TrackSlider(Point oldMouse)
  617. {
  618.     Point newMouse;
  619.     mSelected = true;
  620.     if (!mSliderCursor)
  621.         HideCursor();                            // Hide cursor if mSliderCursor is false
  622.     while (Button()) {
  623.         GetMouse(&newMouse);
  624.         if (!EqualPt(newMouse, oldMouse)) {
  625.             // Mouse moved?
  626.             if (((newMouse.h > mBasePictRect.left) || (mSliderRect.left > mBasePictRect.left))
  627.                 && ((newMouse.h < mBasePictRect.right) || (mSliderRect.right < mBasePictRect.right))) {
  628.  
  629.                 // Move slider if mouse within base picture area
  630.                 OffsetRect(&mSliderRect, newMouse.h - oldMouse.h, 0);
  631.  
  632.                 // Keep Slider from going too far
  633.                 if (mSliderRect.right > mBasePictRect.right)
  634.                     OffsetRect(&mSliderRect, mBasePictRect.right - mSliderRect.right, 0);
  635.                 if (mSliderRect.left < mBasePictRect.left)
  636.                     OffsetRect(&mSliderRect, mBasePictRect.left - mSliderRect.left, 0);
  637.                 oldMouse = newMouse;
  638.                 DrawSelf();
  639.                 DoAction();                        // Send message
  640.                 FocusDraw();
  641.             }
  642.         }
  643.         oldMouse = newMouse;
  644.     }
  645.     mSelected = false;
  646.     DrawSelf();                                    // Display again without selection
  647.     ShowCursor();                                // Display cursor in case it was hidden
  648. }
  649.  
  650.  
  651. // ---------------------------------------------------------------------------
  652. //        • ClickSelf
  653. // ---------------------------------------------------------------------------
  654. //    Move slider while mouse button is down
  655. //  Calls DoAction() when moving
  656.  
  657. void HorzSlider::ClickSelf(const SMouseDownEvent &inMouseDown)
  658. {
  659.     if (PointInSlider(inMouseDown.whereLocal)) {
  660.         // click in slider?
  661.         FocusDraw();
  662.         mSelected = true;
  663.         DrawSelf();                                // update as selected
  664.  
  665.         TrackSlider(inMouseDown.whereLocal);
  666.  
  667.     } else {
  668.         if (PtInRect(inMouseDown.whereLocal, &mBasePictRect)&&(!mSliderOnly)) {
  669.             // click in base?
  670.  
  671.             // Move Slider to center on mouse
  672.             OffsetRect(&mSliderRect, (inMouseDown.whereLocal.h - mSliderRect.left - 
  673.             ((mSliderRect.right - mSliderRect.left)  / 2)), 0);
  674.  
  675.             // Keep slider in base pict
  676.             if (mSliderRect.right > mBasePictRect.right)
  677.                 OffsetRect(&mSliderRect, mBasePictRect.right - mSliderRect.right, 0);
  678.             if (mSliderRect.left < mBasePictRect.left)
  679.                 OffsetRect(&mSliderRect, mBasePictRect.left - mSliderRect.left, 0);
  680.  
  681.             mSelected = true;
  682.             FocusDraw();
  683.             DrawSelf();
  684.             DoAction();                            // Send message
  685.  
  686.             // now track it
  687.             FocusDraw();
  688.             TrackSlider(inMouseDown.whereLocal);
  689.         }
  690.  
  691.     }
  692.  
  693. }
  694.  
  695. // ---------------------------------------------------------------------------
  696. //        • GetSliderValue
  697. // ---------------------------------------------------------------------------
  698. //    Return value of slider
  699.  
  700. long HorzSlider::GetSliderValue(void)
  701. {
  702.     long total;
  703.       float tempvalue;
  704.     total = (mMaxSliderValue - mMinSliderValue);
  705.     tempvalue = ((float)total / (float)(mBaseLength)) *  (mSliderRect.left - mBasePictRect.left);
  706.        return (tempvalue + mMinSliderValue);
  707.  
  708. }
  709.  
  710.  
  711. // ---------------------------------------------------------------------------
  712. //        • SetSliderValue
  713. // ---------------------------------------------------------------------------
  714. //    Set value of slider, update display and send message
  715.  
  716. void HorzSlider::SetSliderValue(long theValue)
  717. {
  718.     long total;
  719.       float tempvalue;
  720.     total = (mMaxSliderValue - mMinSliderValue);
  721.     if (theValue < mMinSliderValue)  theValue = mMinSliderValue;
  722.     if (theValue > mMaxSliderValue)  theValue = mMaxSliderValue;
  723.     tempvalue =    ((float)(theValue- mMinSliderValue)/(float)total)  * (mBaseLength);
  724.          OffsetRect(&mSliderRect,-mSliderRect.left,0);
  725.          OffsetRect(&mSliderRect,tempvalue,0);
  726.               FocusDraw();
  727.             DrawSelf();
  728.             DoAction();                            // Send message
  729.  
  730. }
  731.  
  732. // ---------------------------------------------------------------------------
  733. //        • VertSlider
  734. // ---------------------------------------------------------------------------
  735. //    Default Constructor
  736.  
  737. VertSlider::VertSlider()
  738.     : Slider()
  739.     {
  740.  
  741.     }
  742.  
  743. // ---------------------------------------------------------------------------
  744. //        • VertSlider(ResIDT BasePictRes, ResIDT SliderPictRes)
  745. // ---------------------------------------------------------------------------
  746. //     Create Vertical Slider and assign Pict resource numbers
  747.  
  748. VertSlider::VertSlider(ResIDT BasePictRes, ResIDT SliderPictRes)
  749.     : Slider(BasePictRes, SliderPictRes)
  750.     {
  751.  
  752.     }
  753.  
  754. // ---------------------------------------------------------------------------
  755. //        • VertSlider(ResIDT BasePictRes, ResIDT mSliderPictRes, ResIDT SlideSelectPictRes))
  756. // ---------------------------------------------------------------------------
  757. //     Create Vertical Slider and assign Pict resource numbers
  758.  
  759. VertSlider::VertSlider(ResIDT BasePictRes, ResIDT SliderPictRes, ResIDT SlideSelectPictRes)
  760.     : Slider(BasePictRes, SliderPictRes, SlideSelectPictRes)
  761.     {
  762.  
  763.     }
  764.  
  765. // ---------------------------------------------------------------------------
  766. //        • VertSlider(LStream*)
  767. // ---------------------------------------------------------------------------
  768. //    Construct VertSlider from data in a Stream
  769.  
  770. VertSlider::VertSlider(LStream *inStream)
  771.     : Slider(inStream)
  772.     {
  773.  
  774.     }
  775.  
  776. // ---------------------------------------------------------------------------
  777. //        • CreateVertSliderStream  [static]
  778. // ---------------------------------------------------------------------------
  779. //    Return a new VertSlider object initialized using data from a Stream
  780.  
  781. VertSlider *VertSlider::CreateVertSliderStream(LStream *inStream)
  782. {
  783.     return (new VertSlider(inStream));
  784. }
  785.  
  786. // ---------------------------------------------------------------------------
  787. //        • ~VertSlider
  788. // ---------------------------------------------------------------------------
  789. //    Destructor, deletes any LGWorld objects created
  790.  
  791.  
  792. VertSlider::~VertSlider()
  793. {
  794.  
  795. }
  796.  
  797.  
  798. // ---------------------------------------------------------------------------
  799. //        • TrackSlider
  800. // ---------------------------------------------------------------------------
  801. //    Move slider while mouse button is down
  802. //  Calls DoAction() when moving
  803.  
  804. void VertSlider::TrackSlider(Point oldMouse)
  805. {
  806.     Point newMouse;
  807.     mSelected = true;
  808.     if (!mSliderCursor)
  809.         HideCursor();
  810.     while (Button()) {
  811.         GetMouse(&newMouse);
  812.         if (!EqualPt(newMouse, oldMouse)) {
  813.             // Mouse moved?
  814.             if (((newMouse.v > mBasePictRect.top) || (mSliderRect.top > mBasePictRect.top)) && 
  815.             ((newMouse.v < mBasePictRect.bottom) || (mSliderRect.bottom < mBasePictRect.bottom))) {
  816.             
  817.                 // Move Slider if mouse in base picture area
  818.                 OffsetRect(&mSliderRect, 0, newMouse.v - oldMouse.v);
  819.                 if (mSliderRect.bottom > mBasePictRect.bottom)
  820.                     OffsetRect(&mSliderRect, 0, mBasePictRect.bottom - mSliderRect.bottom);
  821.                 if (mSliderRect.top < mBasePictRect.top)
  822.                     OffsetRect(&mSliderRect, 0, mBasePictRect.top - mSliderRect.top);
  823.  
  824.                 oldMouse = newMouse;
  825.                 DrawSelf();
  826.                 DoAction();                        //  Send message
  827.                 FocusDraw();
  828.             }
  829.         }
  830.         oldMouse = newMouse;
  831.     }
  832.     mSelected = false;
  833.     DrawSelf();                                    // update without selection
  834.     ShowCursor();                                // Show cursor in case it was hidden
  835. }
  836.  
  837. // ---------------------------------------------------------------------------
  838. //        • ClickSelf
  839. // ---------------------------------------------------------------------------
  840. //    Move slider while mouse button is down
  841. //  Calls DoAction() when moving
  842.  
  843. void VertSlider::ClickSelf(const SMouseDownEvent &inMouseDown)
  844. {
  845.     if (PointInSlider(inMouseDown.whereLocal)) {
  846.         // click in slider?
  847.         FocusDraw();
  848.         mSelected = true;
  849.         DrawSelf();
  850.         TrackSlider(inMouseDown.whereLocal);
  851.  
  852.     } else {
  853.         if (PtInRect(inMouseDown.whereLocal, &mBasePictRect)&&(!mSliderOnly)) {
  854.             // click in base?
  855.             FocusDraw();
  856.             mSelected = true;
  857.             OffsetRect(&mSliderRect, 0, (inMouseDown.whereLocal.v - mSliderRect.top - ((mSliderRect.bottom - mSliderRect.top
  858.                                                                                       ) / 2)));
  859.             if (mSliderRect.bottom > mBasePictRect.bottom)
  860.                 OffsetRect(&mSliderRect, 0, mBasePictRect.bottom - mSliderRect.bottom);
  861.             if (mSliderRect.top < mBasePictRect.top)
  862.                 OffsetRect(&mSliderRect, 0, mBasePictRect.top - mSliderRect.top);
  863.  
  864.  
  865.  
  866.             DrawSelf();
  867.             DoAction();
  868.  
  869.             // now track it
  870.             FocusDraw();
  871.             TrackSlider(inMouseDown.whereLocal);
  872.         }
  873.  
  874.     }
  875.  
  876. }
  877.  
  878. // ---------------------------------------------------------------------------
  879. //        • GetSliderValue
  880. // ---------------------------------------------------------------------------
  881. //    Return value of slider
  882.  
  883. long VertSlider::GetSliderValue(void)
  884. {
  885.     long total;
  886.      float tempvalue;
  887.     total = (mMaxSliderValue - mMinSliderValue);
  888.     tempvalue = ((float)total / (float)(mBaseHeight)) *  (mSliderRect.top - mBasePictRect.top);
  889.      return (tempvalue + mMinSliderValue);
  890.  
  891. }
  892.  
  893.  
  894. // ---------------------------------------------------------------------------
  895. //        • SetSliderValue
  896. // ---------------------------------------------------------------------------
  897. //    Set value of slider, update display and send message
  898.  
  899. void VertSlider::SetSliderValue(long theValue)
  900. {
  901.     long total;
  902.       float tempvalue;
  903.     total = (mMaxSliderValue - mMinSliderValue);
  904.     if (theValue < mMinSliderValue)  theValue = mMinSliderValue;
  905.     if (theValue > mMaxSliderValue)  theValue = mMaxSliderValue;
  906.  
  907.         tempvalue =    ((float)(theValue- mMinSliderValue)/(float)total) *  mBaseHeight;
  908.          OffsetRect(&mSliderRect,0,-mSliderRect.top);
  909.          OffsetRect(&mSliderRect,0,tempvalue);
  910.               FocusDraw();
  911.             DrawSelf();
  912.             DoAction();                            // Send message
  913.  
  914. }
  915.