home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-07-15 | 15.6 KB | 624 lines | [TEXT/CWIE] |
- /*******************************************************************************\
- | |
- | HMarqueeCaption.cp ©1997 John C. Daub. All rights reserved. |
- | See the file "HMarqueeCaption README" for full details, instructions, |
- | changes, licensing agreement, etc. Due to the important information |
- | included in that file, if you did not receive a copy of it, please contact |
- | the author for a copy. |
- | |
- | John C. Daub <mailto:hsoi@eden.com> |
- | <http://www.eden.com/~hsoi/> <http://www.eden.com/~hsoi/prog.html> |
- | |
- \*******************************************************************************/
-
-
- #ifdef PowerPlant_PCH
- #include PowerPlant_PCH
- #endif
-
- #include "HMarqueeCaption.h"
-
- #include <PP_KeyCodes.h>
- #include <UDrawingState.h>
- #include <UTextTraits.h>
- #include <UMemoryMgr.h>
-
- #ifndef __TEXTUTILS__
- #include <TextUtils.h>
- #endif
-
-
- #if ( __PowerPlant__ < 0x01608000 ) // version 1.6/CW11
-
- //============================================================================
- // • CreateFromStream [static, public]
- //============================================================================
- // Create a new Caption object from the data in a Stream
-
- HMarqueeCaption*
- HMarqueeCaption::CreateFromStream(
- LStream *inStream)
- {
- return (new HMarqueeCaption(inStream));
- }
-
- #endif
-
-
- //============================================================================
- // • HMarqueeCaption [public]
- //============================================================================
- // Default Constructor
-
- HMarqueeCaption::HMarqueeCaption()
- : mStrHeight(0),
- mLastEvent(0),
- mGWorld(nil),
- mTextLength(0),
- mOffset(0),
- mTextH(nil),
- mTextID(0),
- mTextTraitsID(0),
- mDelay(1),
- mScrollAmount(1),
- mResetOnResize(false)
- {
- InitMarqueeCaption();
- }
-
-
- //============================================================================
- // • HMarqueeCaption [public]
- //============================================================================
- // Copy Constructor
-
- HMarqueeCaption::HMarqueeCaption(
- const HMarqueeCaption &inOriginal)
- : LPane(inOriginal),
- mStrHeight(inOriginal.mStrHeight),
- mLastEvent(inOriginal.mLastEvent),
- mGWorld(nil), // make our own GWorld,
- mOffset(inOriginal.mOffset),
- mTextID(inOriginal.mTextID),
- mTextTraitsID(inOriginal.mTextTraitsID),
- mDelay(inOriginal.mDelay),
- mScrollAmount(inOriginal.mScrollAmount),
- mResetOnResize( inOriginal.mResetOnResize)
- {
- // it'll make it's own copy of the text
-
- mTextH = inOriginal.mTextH;
- ThrowIfOSErr_(::HandToHand( &mTextH ));
- SetTextLength();
-
- InitMarqueeCaption();
- }
-
-
- HMarqueeCaption&
- HMarqueeCaption::operator=(
- const HMarqueeCaption &inOriginal )
- {
- // prevent self-assignment
-
- if ( this == &inOriginal ) {
- return *this;
- }
-
- // pass it back up
-
- LPane::operator=(inOriginal);
-
- // init our stuff
-
- mStrHeight = inOriginal.mStrHeight;
- mLastEvent = inOriginal.mLastEvent;
- mOffset = inOriginal.mOffset;
- mTextID = inOriginal.mTextID;
- mTextTraitsID = inOriginal.mTextTraitsID;
- mDelay = inOriginal.mDelay;
- mScrollAmount = inOriginal.mScrollAmount;
- mResetOnResize = inOriginal.mResetOnResize;
-
- // it'll make it's own copy of the text
-
- mTextH = inOriginal.mTextH;
- ThrowIfOSErr_(::HandToHand( &mTextH ));
- SetTextLength();
-
- // it'll also make it's own GWorld
-
- mGWorld = nil;
-
- InitMarqueeCaption();
-
- return *this;
- }
-
-
- //============================================================================
- // • HMarqueeCaption [public]
- //============================================================================
- // Parameterized constructor
-
- HMarqueeCaption::HMarqueeCaption(
- const SPaneInfo &inPaneInfo,
- ResIDT inTextID,
- ResIDT inTextTraitsID,
- Int16 inDelay,
- Int16 inScrollAmount,
- Boolean inResetOnResize )
- : LPane(inPaneInfo),
- mStrHeight(0),
- mLastEvent(0),
- mGWorld(nil),
- mTextLength(0),
- mOffset(0),
- mTextH(nil),
- mTextID(inTextID),
- mTextTraitsID(inTextTraitsID),
- mDelay(inDelay),
- mScrollAmount(inScrollAmount),
- mResetOnResize(inResetOnResize)
- {
- InitMarqueeCaption();
- }
-
-
- //============================================================================
- // • HMarqueeCaption [public]
- //============================================================================
- // LStream constructor
-
- HMarqueeCaption::HMarqueeCaption(
- LStream *inStream)
- : LPane(inStream),
- mStrHeight(0),
- mTextH(nil),
- mGWorld(nil),
- mLastEvent(0),
- mTextLength(0),
- mOffset(0)
- {
- inStream->ReadData( &mTextID, sizeof(ResIDT) );
- inStream->ReadData( &mTextTraitsID, sizeof(ResIDT) );
- inStream->ReadData( &mDelay, sizeof(Uint16) );
- inStream->ReadData( &mScrollAmount, sizeof(Int16) );
- inStream->ReadData( &mResetOnResize, sizeof(Boolean) );
-
- InitMarqueeCaption();
- }
-
-
- //============================================================================
- // • ~HMarqueeCaption [public, virtual]
- //============================================================================
- // Destructor
-
- HMarqueeCaption::~HMarqueeCaption()
- {
- if ( mTextH ) {
- ::DisposeHandle(mTextH);
- }
-
- DestroyGWorld();
- }
-
-
- //============================================================================
- // • InitMarqueeCaption [private]
- //============================================================================
- // Initializer
-
- void
- HMarqueeCaption::InitMarqueeCaption()
- {
- // create the GWorld
-
- AllocateGWorld();
-
- // get the text
-
- StResource theTextH( 'TEXT', GetTextID() );
-
- // and use it
-
- SetTextHandle( (Handle)theTextH );
- }
-
-
- //============================================================================
- // • SpendTime [public, virtual]
- //============================================================================
- // Draw the Caption
-
- void
- HMarqueeCaption::SpendTime(
- const EventRecord &inMacEvent)
- {
- // we're gonna have fun with modifier keys here :)
-
- // if command is down, we ignore the mDelay amount and just draw as often as
- // SpendTime is called. this should hopefully speed things up a bit (esp
- // on faster computers)
-
- // if option is down, we scroll one more pixel than usual... makes the drawing
- // a little more choppy, but faster. cmd+opt is about as fast as you can get
-
- // if control is down, we just pause... a way to stop the action for a sec
-
- // and if shift is down, we chug in reverse. (to the right)
-
- // hopefully everything should be additive... like cmd-shift-opt would be
- // every time through the loop going 1 more pixel to the right...a fast scroll
- // to the right... and hitting control once in a while would pause you.
-
- // the only problem in here is that all is dependant upon the event loop
- // and if some other app is hogging processor time (like a not-well behaved
- // mac app would do) then these really don't have much impact on the speed of things
-
- // also, we don't "wrap" the scroll necessarily (I should work on this). if we're
- // going normal (to the left), eventually text does wrap around and continue along.
- // but if shift is down, you can't go backwards to the beginning and have it
- // wrap around to the end....maybe something to add later :)
-
- if ( (inMacEvent.modifiers & controlKey) != 0 )
- return;
-
- if ( ((inMacEvent.modifiers & cmdKey) != 0)
- || (inMacEvent.when - GetLastEvent() ) > GetDelay() )
- {
- SetLastEvent( inMacEvent.when );
- IncrementOffset( GetScrollAmount() );
-
- if ( (inMacEvent.modifiers & optionKey) != 0 ) {
- IncrementOffset( 1 );
- }
-
- if ( (inMacEvent.modifiers & shiftKey) != 0 ) {
- IncrementOffset( -(GetScrollAmount() * 2) );
-
- if ( (inMacEvent.modifiers & optionKey) != 0 ) {
- IncrementOffset( -2 ); // have to remove 2..one to negate the above added
- // and one more to actually do something
- }
- }
-
- SDimension16 frameSize;
- GetFrameSize( frameSize );
-
- if ( GetOffset() > (GetTextLength() + frameSize.width) )
- SetOffset( 0 );
- else if ( GetOffset() <= 0 )
- SetOffset( GetTextLength() + frameSize.width );
-
- Draw( nil );
- }
- }
-
-
- //============================================================================
- // • Draw [public, virtual]
- //============================================================================
- // Draw the Caption. We have to override Draw so as to be able to use the
- // GWorld for drawing.
-
- void
- HMarqueeCaption::Draw(
- RgnHandle inSuperDrawRgnH )
- {
- Rect frame;
-
- // make sure we're in a state to bother drawing
-
- if ( IsVisible() &&
- FocusDraw() &&
- CalcPortFrameRect(frame) &&
- ((inSuperDrawRgnH == nil) || ::RectInRgn(&frame, inSuperDrawRgnH)) )
- {
- // get our frame
-
- CalcLocalFrameRect( frame );
-
- // store off the GWorld
-
- CGrafPtr theSavePort;
- GDHandle theSaveDevice;
- ::GetGWorld( &theSavePort, &theSaveDevice );
-
- // convert
-
- Rect gwRect = frame;
- ::LocalToGlobal( &topLeft(gwRect) );
- ::LocalToGlobal( &botRight(gwRect) );
-
- // set up our GWorld for drawing
-
- ::SetGWorld( mGWorld, nil );
- ::SetOrigin( frame.left, frame.top );
- ::LockPixels(::GetGWorldPixMap(mGWorld));
- ApplyForeAndBackColors();
- ::EraseRect(&frame);
-
- // draw it
-
- LPane::Draw( inSuperDrawRgnH );
-
- // restore
-
- ::SetGWorld(theSavePort, theSaveDevice);
-
- // and blit
-
- StColorState::Normalize();
- ::CopyBits(&((GrafPtr)mGWorld)->portBits,
- &((GrafPtr)theSavePort)->portBits,
- &frame, &frame, srcCopy, nil);
-
- ::UnlockPixels(::GetGWorldPixMap(mGWorld));
- }
- }
-
-
- //============================================================================
- // • DrawSelf [protected, virtual]
- //============================================================================
- // Draw the Caption
-
- void
- HMarqueeCaption::DrawSelf()
- {
- // get the rect and clip to it
- Rect frame;
-
- CalcLocalFrameRect(frame);
- ::InsetRect( &frame, 2, 2 );
- StClipRgnState clipSave( frame );
-
- // set the text traits
-
- UTextTraits::SetPortTextTraits( GetTextTraitsID() );
-
- // set up the colors
-
- RGBColor textColor;
- ::GetForeColor(&textColor);
- ApplyForeAndBackColors();
-
- if ( !IsActive() )
- {
- // lighten the text color a bit
-
- textColor.red = textColor.red + 65535 >> 1;
- textColor.green = textColor.green + 65535 >> 1;
- textColor.blue = textColor.blue + 65535 >> 1;
- }
-
- // restore the text color
-
- ::RGBForeColor(&textColor);
-
- // and draw the text
- ::MoveTo( frame.right - GetOffset(), frame.top + GetStringHeight() );
- StHandleLocker lock(mTextH);
- ::DrawText( *mTextH, 0, ::GetHandleSize(mTextH) );
- }
-
-
- //============================================================================
- // • Reset [protected, virtual]
- //============================================================================
- // Reset the status to default/starting values
-
- void
- HMarqueeCaption::Reset()
- {
- FontInfo fontInfo;
-
- SetOffset( 0 );
- SetLastEvent( 0 );
- UTextTraits::SetPortTextTraits( GetTextTraitsID() );
- ::GetFontInfo( &fontInfo );
- SetStringHeight( fontInfo.ascent );
- SetTextLength();
- }
-
-
- //============================================================================
- // • ActivateSelf [protected, virtual]
- //============================================================================
- // We need to force a redraw when the pane becomes active so that it
- // will draw properly.
-
- void
- HMarqueeCaption::ActivateSelf()
- {
- if ( mActive == triState_On ) {
- Refresh();
- StartRepeating();
- }
- }
-
-
- //============================================================================
- // • DeactivateSelf [protected, virtual]
- //============================================================================
- // We need to force a redraw when the pane becomes deactivated
-
- void
- HMarqueeCaption::DeactivateSelf()
- {
- if ( mActive == triState_Off || mActive == triState_Latent ) {
- Refresh();
- StopRepeating();
- }
- }
-
-
- //============================================================================
- // • StripCRLF [public, virtual]
- //============================================================================
- // Scans the text handle and strips out any carriage returns and/or
- // line feeds that it finds (they won't show up very well)
-
- void
- HMarqueeCaption::StripCRLF()
- {
- StHandleLocker lock(mTextH);
-
- Ptr thePtr = *mTextH;
-
- Size theSize = ::GetHandleSize(mTextH);
-
- for ( Int32 i = 1; i <= theSize; ++i )
- {
- if ( (*thePtr == char_LineFeed) || (*thePtr == char_Return) ) {
- *thePtr = char_Space;
- }
-
- ++thePtr;
- }
- }
-
-
- //============================================================================
- // • SetTextHandle [public, virtual]
- //============================================================================
- // Sets the text to use to the given Handle. We make a copy of the given
- // Handle (so caller must dispose of the Handle)
-
- void
- HMarqueeCaption::SetTextHandle( Handle inTextH )
- {
- // If the new Handle is nil, we'll just stop right here.
-
- if ( inTextH == nil ) {
- SignalPStr_("\pinTextH == nil");
- return;
- }
-
- // Just in case we're repeating, we should stop.
-
- StopRepeating();
-
- // get rid of any old text
-
- if ( mTextH != nil ) {
- ::DisposeHandle(mTextH);
- mTextH = nil;
- }
-
- // make a copy of the new text
-
- mTextH = inTextH;
- ThrowIfOSErr_(::HandToHand( &mTextH ));
-
- // strip any cr's and lf's
-
- StripCRLF();
-
- // reset things
-
- Reset();
-
- // and start repeating
-
- StartRepeating();
- }
-
-
-
- //============================================================================
- // • AllocateGWorld [protected, virtual]
- //============================================================================
- // Allocates our GWorld
-
- void
- HMarqueeCaption::AllocateGWorld()
- {
- // dispose of one, if needed
-
- DestroyGWorld();
-
- // we'll allocate a GWorld the size of our frame
-
- Rect frame;
- CalcLocalFrameRect(frame);
- ::LocalToGlobal( &topLeft(frame) );
- ::LocalToGlobal( &botRight(frame) );
-
- QDErr err = ::NewGWorld( &mGWorld, 0, &frame, nil, nil, 0 );
- if ( err == memFullErr ) {
- // if our heap is full, try temporary memory
- err = ::NewGWorld( &mGWorld, 0, &frame, nil, nil, useTempMem );
- }
-
- ThrowIfOSErr_(err);
- ThrowIfNil_(mGWorld);
- }
-
-
-
- //============================================================================
- // • DestroyGWorld [protected, virtual]
- //============================================================================
- // Disposes of our GWorld
-
- void
- HMarqueeCaption::DestroyGWorld()
- {
- if ( mGWorld != nil ) {
- ::DisposeGWorld(mGWorld);
- mGWorld = nil;
- }
- }
-
-
- //============================================================================
- // • ResizeFrameBy [public, virtual]
- //============================================================================
- // If the frame size changes, we have to reallocate our GWorld
-
- void
- HMarqueeCaption::ResizeFrameBy(
- Int16 inWidthDelta,
- Int16 inHeightDelta,
- Boolean inRefresh)
- {
- // let the normal resizing occur
- LPane::ResizeFrameBy(inWidthDelta, inHeightDelta, inRefresh);
-
- // rellocate the GWorld
- AllocateGWorld();
-
- // and reset if desired
-
- if ( GetResetOnResize() ) {
- Reset();
- }
- }
-
-
- // the following functions are declared inline in the header file. The #pragma
- // mark let's them show up in the CW IDE's function popup for ease of navigation
- // and reference. :-)
-
- #pragma mark HMarqueeCaption::GetStringHeight
- #pragma mark HMarqueeCaption::SetStringHeight
- #pragma mark HMarqueeCaption::GetLastEvent
- #pragma mark HMarqueeCaption::SetLastEvent
- #pragma mark HMarqueeCaption::GetTextLength
- #pragma mark HMarqueeCaption::SetTextLength
- #pragma mark HMarqueeCaption::GetOffset
- #pragma mark HMarqueeCaption::SetOffset
- #pragma mark HMarqueeCaption::IncrementOffset
- #pragma mark HMarqueeCaption::GetTextID
- #pragma mark HMarqueeCaption::SetTextID
- #pragma mark HMarqueeCaption::GetTextTraitsID
- #pragma mark HMarqueeCaption::SetTextTraitsID
- #pragma mark HMarqueeCaption::GetDelay
- #pragma mark HMarqueeCaption::SetDelay
- #pragma mark HMarqueeCaption::GetScrollAmount
- #pragma mark HMarqueeCaption::SetScrollAmount
- #pragma mark HMarqueeCaption::GetResetOnResize
- #pragma mark HMarqueeCaption::SetResetOnResize