home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / PowerPlant / CURLPushButton 2.3 / CURLPushButton.cp < prev    next >
Encoding:
Text File  |  1997-07-21  |  16.2 KB  |  635 lines  |  [TEXT/CWIE]

  1. /*******************************************************************************\
  2. |                                                                                |
  3. | CURLPushButton.cp ©1997 John C. Daub.  All rights reserved                    |
  4. |                                                                                |
  5. | See the file "CURLPushButton README" for full details, instructions, changes, |
  6. | licensing agreement, etc.  Due to the important information included in that    |
  7. | file, if you did not receive a copy of it, please contact the author for        |
  8. | a copy.                                                                        |
  9. |                                                                                |
  10. | John C. Daub <mailto:hsoi@eden.com>                                            |
  11. | <http://www.eden.com/~hsoi/>  <http://www.eden.com/~hsoi/prog.html>            |
  12. |                                                                                |
  13. \*******************************************************************************/
  14.  
  15.  
  16. #ifdef PowerPlant_PCH
  17. #include PowerPlant_PCH
  18. #endif
  19.  
  20.  
  21. #include "CURLPushButton.h"
  22.  
  23. #include <LString.h>
  24. #include <UTextTraits.h>
  25. #include <LStream.h>
  26. #include <UDrawingUtils.h>
  27. #include <PP_Constants.h>
  28. #include <LDragAndDrop.h>
  29. #include <LDragTask.h>
  30.  
  31. #ifndef __TEXTEDIT__
  32. #include <TextEdit.h>
  33. #endif
  34.  
  35.  
  36. #if ( __PowerPlant__ < 0x01608000 )
  37.  
  38. //========================================================================
  39. //    • CreateFromStream                            [static, public]
  40. //========================================================================
  41. //    The CreateFromStream routine, only used if compiled in conjunction
  42. //    with versions of PowerPlant less than v1.6 (CW11).  With CW11/v1.6,
  43. //    the RegisterClass_() macro makes these CreateFromStream routines
  44. //    unnecessary, so we'll conditionally preprocess it out
  45. //
  46.  
  47. CURLPushButton*    
  48. CURLPushButton::CreateFromStream(
  49.     LStream *inStream )
  50. {
  51. #ifdef DEBUG_NEW
  52.     return ( NEW CURLPushButton( inStream ) );
  53. #else
  54.     return ( new CURLPushButton(inStream) );
  55. #endif
  56. }
  57.  
  58. #endif
  59.  
  60.  
  61. //========================================================================
  62. //    • CURLPushButton                            [public]
  63. //========================================================================
  64. //    Default constructor
  65.  
  66. CURLPushButton::CURLPushButton()
  67.     : mTextTraitsID(0),
  68.     mHiliteTextTraitsID(-1),
  69.     mUseHiliteColor(false),
  70.     mUseInvertRect(false),
  71.     mURL("\p"),
  72.     mTitleText("\p")
  73. {
  74.     mValue = Button_Off;    // no way in PP to set mValue w/o broadcasting :(
  75.  
  76. #if _CURLPushButton_DO_DND_
  77.     mDoDragAndDrop = true;
  78. #endif
  79.  
  80.     SetHiliteColor( 0, 0, 0 );
  81. }
  82.  
  83.  
  84. //========================================================================
  85. //    • CURLPushButton                            [public]
  86. //========================================================================
  87. //    Copy constructor
  88.  
  89. CURLPushButton::CURLPushButton(
  90.     const CURLPushButton &inOriginal )
  91.         : LControl(inOriginal),
  92.         mTextTraitsID(inOriginal.mTextTraitsID),
  93.         mHiliteTextTraitsID(inOriginal.mHiliteTextTraitsID),
  94.         mUseHiliteColor(inOriginal.mUseHiliteColor),
  95.         mUseInvertRect(inOriginal.mUseInvertRect),
  96.         mURL(inOriginal.mURL),
  97.         mTitleText(inOriginal.mTitleText)
  98. {    
  99. #if _CURLPushButton_DO_DND_
  100.     mDoDragAndDrop = inOriginal.mDoDragAndDrop;
  101. #endif
  102.  
  103.     RGBColor theColor;
  104.     inOriginal.GetHiliteColor( theColor );
  105.     SetHiliteColor( theColor );
  106. }
  107.  
  108.  
  109. //========================================================================
  110. //    • operator=                                    [public]
  111. //========================================================================
  112. //    Assignment operator
  113.  
  114. CURLPushButton&
  115. CURLPushButton::operator=(
  116.     const CURLPushButton &inOriginal )
  117. {
  118.     // check for self-assignment
  119.     
  120.     if ( this == &inOriginal ) {
  121.         return *this;
  122.     }
  123.  
  124.     // pass it back up the chain
  125.     
  126.     LControl::operator=(inOriginal);
  127.  
  128.     // initialize
  129.     mTextTraitsID = inOriginal.mTextTraitsID;
  130.     mHiliteTextTraitsID = inOriginal.mHiliteTextTraitsID;
  131.     mUseHiliteColor = inOriginal.mUseHiliteColor;
  132.     mUseInvertRect = inOriginal.mUseInvertRect;
  133.     
  134.     mURL = inOriginal.mURL;
  135.     mTitleText = inOriginal.mTitleText;
  136.     
  137. #if _CURLPushButton_DO_DND_
  138.     mDoDragAndDrop = inOriginal.mDoDragAndDrop;
  139. #endif
  140.  
  141.     RGBColor theColor;
  142.     inOriginal.GetHiliteColor( theColor );
  143.     SetHiliteColor( theColor );
  144.  
  145.     return *this;
  146. }
  147.  
  148.  
  149. //========================================================================
  150. //    • CURLPushButton                            [public]
  151. //========================================================================
  152. //    Parameterized constructor
  153.  
  154. CURLPushButton::CURLPushButton(
  155.     const SPaneInfo        &inPaneInfo,
  156.     const SURLpbInfo &inParamInfo )
  157.         : LControl(    inPaneInfo,
  158.                     inParamInfo.valueMessage,
  159.                     inParamInfo.value,
  160.                     inParamInfo.minValue,
  161.                     inParamInfo.maxValue ),
  162.         mTextTraitsID(inParamInfo.textTraitsID),
  163.         mHiliteTextTraitsID(inParamInfo.hiliteTextTraitsID),
  164.         mUseHiliteColor(inParamInfo.useHiliteColor),
  165.         mUseInvertRect(inParamInfo.useInvertRect),
  166.         mURL(inParamInfo.URL),
  167.         mTitleText(inParamInfo.titleText)
  168. {
  169. #if _CURLPushButton_DO_DND_
  170.     mDoDragAndDrop = true;
  171. #endif
  172.  
  173.     SetHiliteColor( inParamInfo.hiliteColor );
  174. }
  175.  
  176.  
  177. //========================================================================
  178. //    • CURLPushButton                            [public]
  179. //========================================================================
  180. //    LStream constructor
  181.  
  182. CURLPushButton::CURLPushButton(
  183.     LStream *inStream )
  184.         : LControl( inStream ),
  185.         mUseInvertRect(false)
  186. {
  187.     mValue = Button_Off;
  188.     
  189.     inStream->ReadPString(mTitleText);
  190.     inStream->ReadPString(mURL);
  191.     inStream->ReadData( &mTextTraitsID, sizeof(ResIDT) );
  192.     inStream->ReadData( &mHiliteTextTraitsID, sizeof(ResIDT) );
  193.     inStream->ReadData( &mUseHiliteColor, sizeof(Boolean) );
  194.     inStream->ReadData( &mHiliteColor, sizeof(RGBColor) );
  195.  
  196. #if _CURLPushButton_DO_DND_
  197.     mDoDragAndDrop = true;
  198. #endif
  199.  
  200. }
  201.  
  202.  
  203. //========================================================================
  204. //    • ~CURLPushButton                            [public, virtual]
  205. //========================================================================
  206. //    Destructor
  207.  
  208. CURLPushButton::~CURLPushButton()
  209. {
  210.     // nothing
  211. }
  212.  
  213.  
  214. //========================================================================
  215. //    • SetValue                                    [public, virtual]
  216. //========================================================================
  217. //    Technically we don't need a SetValue routine for CURLPushButton...it
  218. //    does nothing.  However since LControl does define this method
  219. //    (and if called, we do NOT want LControl::SetValue to be called)
  220. //    we need to override SetValue just to hide LControl's version.
  221.  
  222. void
  223. CURLPushButton::SetValue(
  224.     Int32 inValue )
  225. {
  226. #pragma unused(inValue)
  227.  
  228.     // just for giggles....
  229.     
  230.     mValue = Button_Off;
  231. }
  232.  
  233.  
  234. //========================================================================
  235. //    • GetURL                                    [public, virtual]
  236. //========================================================================
  237. //    Returns the URL associated with the button.
  238. //
  239. //    GetDescriptor returns the title of the button.  Many times the URL
  240. //    and the title of the button will be the same, but they do not have to
  241. //    be (e.g. button title is your name and URL points to your web page).
  242. //    
  243. //    When you want the URL, you should call GetURL and NOT GetDescriptor.
  244. //    GetURL is also set up so that if mURL is nil, it will automatically
  245. //    return the button title (for added flexibility).  However, there is
  246. //    no check made to ensure the button title is a valid URL.
  247.  
  248. StringPtr
  249. CURLPushButton::GetURL(
  250.     Str255 outURL ) const
  251. {
  252.     if ( mURL[0] == 0 ) {
  253.  
  254.         // URL string is empty so return the button title
  255.         return LString::CopyPStr( mTitleText, outURL );        
  256.     
  257.     } else {
  258.  
  259.         // URL string is not empty, so return it
  260.         return LString::CopyPStr( mURL, outURL );
  261.     }
  262. }
  263.  
  264. //    This is another version of GetURL, however it does not take any
  265. //    input parameters.
  266.  
  267. StringPtr
  268. CURLPushButton::GetURL()
  269. {
  270.     if ( mURL[0] == 0 ) {
  271.         return mTitleText;
  272.     } else {
  273.         return mURL;
  274.     }
  275. }
  276.  
  277.  
  278. //========================================================================
  279. //    • SetURL                                    [public, virtual]
  280. //========================================================================
  281. //    Sets the URL to the specified input parameter.
  282. //
  283.  
  284. void
  285. CURLPushButton::SetURL(
  286.     ConstStr255Param inURL )
  287. {
  288.     mURL = inURL;
  289. }
  290.  
  291.  
  292. //========================================================================
  293. //    • GetDescriptor                                [public, virtual]
  294. //========================================================================
  295. //    Return the title text of the button
  296. //
  297.     
  298. StringPtr
  299. CURLPushButton::GetDescriptor(
  300.     Str255    outDescriptor) const
  301. {
  302.     return LString::CopyPStr(mTitleText, outDescriptor);
  303. }
  304.  
  305. StringPtr
  306. CURLPushButton::GetDescriptor()
  307. {
  308.     return mTitleText;
  309. }
  310.  
  311.  
  312. //========================================================================
  313. //    • SetDescriptor                                [public, virtual]
  314. //========================================================================
  315. //    Reset button title and update region
  316. //
  317.  
  318. void
  319. CURLPushButton::SetDescriptor(
  320.     ConstStr255Param inDescriptor)
  321. {
  322.     mTitleText = inDescriptor;
  323.     Refresh();
  324. }
  325.  
  326.  
  327. //========================================================================
  328. //    • HotSpotResult                                [protected, virtual]
  329. //========================================================================
  330. //    Unlike LTextButton, which behaves like a radio button, CURLPushButton
  331. //    behaves like a push button.
  332. //
  333.  
  334. void
  335. CURLPushButton::HotSpotResult(
  336.     Int16 inHotSpot )
  337. {
  338.     // Undo the hilighting
  339.     
  340.     HotSpotAction ( inHotSpot, false, true );
  341.  
  342.     // broadcast the value message...even tho the value doesn't
  343.     // change, send the message to inform listeners that the
  344.     // button was clicked
  345.     
  346.     BroadcastValueMessage();
  347. }
  348.  
  349.  
  350. //========================================================================
  351. //    • HotSpotAction                                [protected, virtual]
  352. //========================================================================
  353.  
  354. void
  355. CURLPushButton::HotSpotAction(
  356.     Int16    inHotSpot,
  357.     Boolean    inCurrInside,
  358.     Boolean    inPrevInside)
  359. {
  360. #pragma unused(inHotSpot)
  361.  
  362.     Int16 theJust = teCenter; // declare and give it some default value
  363.     
  364.     if (inCurrInside) {
  365.         if (!inPrevInside) {
  366.         
  367.             // click is inside the button (depressed/hilited state)
  368.             
  369.             // get the button frame
  370.             
  371.             Rect    frame;
  372.             CalcLocalFrameRect(frame);
  373.             
  374.             
  375.             if ( GetUseInvertRect() ) {
  376.  
  377.                 // if we want to just use InvertRect, do it and return.                
  378.                 ::InvertRect(&frame);
  379.                 return;
  380.             }
  381.             
  382.             
  383.             if ( GetHiliteTextTraitsID() > -1 ) {
  384.  
  385.                 // we're using a second text trait, so set it up
  386.                 
  387.                 // need to erase first to clean things up
  388.                 
  389.                 ApplyForeAndBackColors();
  390.                 ::EraseRect(&frame);
  391.                 theJust = UTextTraits::SetPortTextTraits( GetHiliteTextTraitsID() );
  392.             
  393.             } else if ( GetUseHiliteColor() ) {
  394.  
  395.                 // instead we'll reuse the main traits, but just a custom color
  396.                 
  397.                 theJust = UTextTraits::SetPortTextTraits( GetTextTraitsID() );
  398.                 RGBColor theHiliteColor;
  399.                 GetHiliteColor( theHiliteColor );
  400.                 ::RGBForeColor( &theHiliteColor );
  401.  
  402.             } else {
  403.  
  404.                 // nada specified, so just invert!
  405.                 
  406.                 theJust = UTextTraits::SetPortTextTraits( GetTextTraitsID() );
  407.                 ::TextMode( srcXor );
  408.             }
  409.  
  410.             // check the justification
  411.             
  412.             if ( theJust == teFlushDefault ) {
  413.                 theJust = ::GetSysDirection();
  414.             }
  415.             
  416.             // finally, draw it
  417.                         
  418.             UTextDrawing::DrawWithJustification((Ptr)&mTitleText[1], mTitleText[0],
  419.                                             frame, theJust );
  420.         }
  421.  
  422.     } else {
  423.     
  424.         if (inPrevInside) {
  425.         
  426.             // click, but moved outside the button (tracking)
  427.             
  428.             Rect    frame;
  429.             CalcLocalFrameRect(frame);
  430.             
  431.             if ( GetUseInvertRect() ) {
  432.  
  433.                 // if we want to just use InvertRec, do so and return                
  434.                 ::InvertRect( &frame );
  435.                 return;
  436.             }
  437.  
  438.             // since we've moved outside the button, the button should
  439.             // just look like it does normally.
  440.             
  441.  
  442.             // need to erase first to clean things up
  443.             ApplyForeAndBackColors();
  444.             ::EraseRect(&frame);
  445.  
  446.             theJust = UTextTraits::SetPortTextTraits(GetTextTraitsID());
  447.             if (theJust == teFlushDefault) {
  448.                 theJust = ::GetSysDirection();
  449.             }
  450.                         
  451.             UTextDrawing::DrawWithJustification((Ptr)&mTitleText[1], mTitleText[0],
  452.                                             frame, theJust );
  453.         }
  454.     }
  455. }
  456.  
  457.  
  458. //========================================================================
  459. //    • DrawSelf                                    [protected, virtual]
  460. //========================================================================
  461.  
  462. void
  463. CURLPushButton::DrawSelf()
  464. {
  465.     StTextState        origTextState;
  466.     StColorPenState    origCPenState;
  467.  
  468.     // Configure the text state. If the button is selected,
  469.     // modify the text style.
  470.  
  471.     Int16 theJust = UTextTraits::SetPortTextTraits(GetTextTraitsID());
  472.  
  473.     // get the color of the text
  474.     
  475.     RGBColor    textColor;
  476.     ::GetForeColor( &textColor );
  477.     
  478.     ApplyForeAndBackColors();
  479.     
  480.     if ( !IsActive() ) {
  481.         textColor.red = textColor.red + 65535 >> 1;
  482.         textColor.green = textColor.green + 65535 >> 1;
  483.         textColor.blue = textColor.blue + 65535 >> 1;
  484.     }
  485.     
  486.     ::RGBForeColor( &textColor );
  487.     
  488.     // Draw the text.
  489.     
  490.     Rect theFrame;
  491.     CalcLocalFrameRect(theFrame);
  492.  
  493.     if (theJust == teFlushDefault) {
  494.         theJust = ::GetSysDirection();
  495.     }
  496.     
  497.     UTextDrawing::DrawWithJustification((Ptr)&mTitleText[1], mTitleText[0],
  498.                                         theFrame, theJust);    
  499. }
  500.  
  501.  
  502. //========================================================================
  503. //    • ActivateSelf                                [protected, virtual]
  504. //========================================================================
  505. //    We need to force a redraw when the pane becomes active so that it
  506. //    will draw properly.
  507.  
  508. void
  509. CURLPushButton::ActivateSelf()
  510. {
  511.     if ( mActive == triState_On ) {
  512.         Refresh();
  513.     }
  514. }
  515.  
  516.  
  517. //========================================================================
  518. //    • DeactivateSelf                            [protected, virtual]
  519. //========================================================================
  520. //    We need to force a redraw when the pane becomes deactivated
  521.  
  522. void
  523. CURLPushButton::DeactivateSelf()
  524. {
  525.     if ( mActive == triState_Off || mActive == triState_Latent ) {
  526.         Refresh();
  527.     }
  528. }
  529.  
  530.  
  531. // the following routines are only utilized if we are supporting drag and
  532. // drop, so let's process them out to save on code size if people don't
  533. // want them.
  534.  
  535. #if _CURLPushButton_DO_DND_
  536.  
  537. //========================================================================
  538. //    • ClickSelf                                    [protected, virtual]
  539. //========================================================================
  540. //    Provides us some drag and drop capabilities with the control. The HIG
  541. //    of this is a bit odd since this is a control, so we'll only do this
  542. //    if the shift key is held down. Else, just click as normal.
  543. //
  544. //    Code courtesy of Matt Brunk.
  545.  
  546. void
  547. CURLPushButton::ClickSelf(
  548.     const SMouseDownEvent &inMouseDown)
  549. {
  550.     // Only do a drag if we want to do it for this object, the Drag Manager is
  551.     // present and the Shift key is pressed.
  552.  
  553.     if ( GetDoDragAndDrop() &&
  554.             LDragAndDrop::DragAndDropIsPresent() &&
  555.             (inMouseDown.macEvent.modifiers & shiftKey) ) {
  556.  
  557.         // If we leave the window, the drag manager will be changing thePort,
  558.         // so we'll make sure thePort remains properly set.
  559.  
  560.         mSuperView->FocusDraw();
  561.         CreateDragEvent(inMouseDown);
  562.         mSuperView->OutOfFocus(nil);
  563.  
  564.     } else {
  565.         LControl::ClickSelf(inMouseDown);
  566.     }
  567. }
  568.  
  569.  
  570. //========================================================================
  571. //    • CreateDragEvent                            [protected, virtual]
  572. //========================================================================
  573. //    Establish the drag and drop event. Strip the URL of any extraneous
  574. //    characters and do the drag task.
  575. //
  576. //    Code courtesy of Matt Brunk.
  577.  
  578. void
  579. CURLPushButton::CreateDragEvent(
  580.     const SMouseDownEvent &inMouseDown )
  581. {
  582.     void    *ptr;
  583.     Int32    length;
  584.     Str255    theURL;
  585.     
  586.     GetURL( theURL );
  587.     
  588.     // If the URL is enclosed by '<' and '>', we get the enclosing text.
  589.  
  590.     if (theURL[0] >= 3 && theURL[1] == '<' && theURL[theURL[0]] == '>') {
  591.  
  592.         ptr    = (void *)&theURL[2];    // character after '<'
  593.         length = theURL[0] - 2;            // character before '<'
  594.  
  595.     } else {
  596.  
  597.         ptr    = (void *)&theURL[1];    // all of the text
  598.         length = theURL[0];    
  599.     }
  600.     
  601.     Rect    theRect;
  602.     CalcLocalFrameRect(theRect);
  603.  
  604.     LDragTask theDragTask(    inMouseDown.macEvent,
  605.                             theRect,
  606.                             1,                        // Item Reference
  607.                             'TEXT',                    // flavor type
  608.                             ptr,                    // pointer to text
  609.                             length,                    // length of text
  610.                             0L                        // flavor flags
  611.                             );
  612.  
  613. }
  614.  
  615. #endif // _CURLPushButton_DO_DND_
  616.  
  617.  
  618. // the following functions are declared inline in the header file. The #pragma
  619. // mark let's them show up in the CW IDE's function popup for ease of navigation
  620. // and reference. :-)
  621.  
  622. #pragma mark CURLPushButton::GetTextTraitsID
  623. #pragma mark CURLPushButton::SetTextTraitsID
  624. #pragma mark CURLPushButton::GetHiliteTextTraitsID
  625. #pragma mark CURLPushButton::SetHiliteTextTraitsID
  626. #pragma mark CURLPushButton::GetUseHiliteColor
  627. #pragma mark CURLPushButton::SetUseHiliteColor
  628. #pragma mark CURLPushButton::GetHiliteColor
  629. #pragma mark CURLPushButton::SetHiliteColor
  630. #pragma mark CURLPushButton::SetInvertRect
  631. #pragma mark CURLPushButton::GetInvertRect
  632. #pragma mark CURLPushButton::SetUseInvertRect
  633. #pragma mark CURLPushButton::GetUseInvertRect
  634. #pragma mark CURLPushButton::GetDoDragAndDrop
  635. #pragma mark CURLPushButton::SetDoDragAndDrop