home *** CD-ROM | disk | FTP | other *** search
-
- #include "ocheaders.h"
- #include "CBaseControl.h"
- #include "CErrorControl.h"
- #include "CTickerControl.h"
- #include "CTick.h"
- #include "FnAssert.h"
- #include "Colors.h"
- #include "CTickerError.h"
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::CTick
- //
-
- CTick::CTick( CTickerControl* pctl, long id )
- {
- const Rect nullRect = { 0, 0, 0, 0 };
- const Point nullSize = { 0, 0 };
-
- mDataItemID = id;
- mControl = pctl;
- mCached = false;
- mXLocation = 0;
- mFontInfo = NULL;
- mSize = nullSize;
- mBoundsRect = nullRect;
- mGWorld = NULL;
- mPixMap = NULL;
- mStrName = NULL;
- mStrValue = NULL;
- mRenderState = renderOFF;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::~CTick
- //
-
- CTick::~CTick()
- {
- Render(renderOFF); // avoid code duplication by calling Render() directly
-
- if ( mFontInfo )
- {
- ::CoTaskMemFree(mFontInfo);
- mFontInfo = NULL;
- }
-
- if ( mStrName )
- {
- ::CoTaskMemFree(mStrName);
- mStrName = NULL;
- }
- if ( mStrValue )
- {
- ::CoTaskMemFree(mStrValue);
- mStrValue = NULL;
- }
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::Render
- //
- // Synopsis: Creates an offscreen gworld with the text rendered in it.
- //
-
- void CTick::Render(RenderState renderState)
- {
- if ( renderState == renderON && mRenderState == renderOFF)
- {
- try
- {
- // Compute the bounds of the offscreen gworld, as determined by the
- // text when it's draw in its characteristic offset mode.
-
- // Does this tick have a value?
- Boolean isValue = (strlen(mStrValue) != 0);
-
- // Get the size of the name
- Point sizeName = {0,0};
- Str255 strName;
- strcpy((char *)strName, mStrName);
- strcat((char *)strName, " ");
- if (isValue)
- strcat((char *)strName, " ");
- c2pstr((char *)strName);
- GetTextSize(strName, &sizeName);
-
- // Get the size of the value(s)
- Point sizeValue = {0,0};
- if (isValue)
- {
- Str255 strValue;
- strcpy((char *)strValue, mStrValue);
- strcat((char *)strValue, " ");
- c2pstr((char *)strValue);
- GetTextSize(strValue, &sizeValue);
- }
-
- // Text sizes
- mSize.v = sizeName.v > sizeValue.v ? sizeName.v : sizeValue.v;
- mSize.h = sizeName.h + sizeValue.h;
-
- // Offset the names from the values
- short offsetBy = (mSize.v / 3); // the default is dependent on text height
- if ( mControl->GetUserOffsetValues() ) // did the user specify in a parameter?
- offsetBy = mControl->GetOffsetValues(); // use the input value instead
- mSize.v += ABSVAL(offsetBy); // adjust text height for the offset, whatever it is
-
- // set the size of the offscreen gworld
- ::SetRect(&mBoundsRect, 0, 0, mSize.h, mSize.v);
-
- // we shouldn't already have a gworld
- ASSERT((mGWorld == NULL), "Unexpected non-NULL GWorld!");
- ASSERT((mPixMap == NULL), "Unexpected non-NULL PixMap!");
-
- // make the new gworld if needed
- mPixMap = NULL;
- QDErr err = ::NewGWorld( &mGWorld, 8, &mBoundsRect, 0, nil, 0 );
- if ( !err )
- mPixMap = ::GetGWorldPixMap( mGWorld );
-
- // NOW we should have a gworld
- if ( mGWorld == NULL || mPixMap == NULL )
- throw CTickerError(TICK_GWORLD_ALLOCATION_ERROR, this);
-
- // Store the current port and device before switching to the offscreen world.
- CGrafPtr currentPort;
- GDHandle currentDevice;
- ::GetGWorld( ¤tPort, ¤tDevice );
-
- // Switch to the offscreen GWorld and lock the offscreen buffer in memory.
- ::SetGWorld( mGWorld, nil );
- ::LockPixels( mPixMap );
- ::HLock((Handle)mPixMap);
-
- // Draw the text into the offsceen world...
-
- // generate Pascal strings for drawing
- Str255 nameStringToDraw, valueStringToDraw;
- strcpy((char *)nameStringToDraw, mStrName);
- c2pstr((char *)nameStringToDraw);
- strcpy((char *)valueStringToDraw, mStrValue);
- c2pstr((char *)valueStringToDraw);
-
- // Set colors
- RGBColor foreColor, backColor;
- mControl->GetBackColor(&backColor);
- mControl->GetForeColor(&foreColor);
- ::RGBBackColor(&backColor);
- ::RGBForeColor(&foreColor);
-
- // Erase.
- EraseImage();
-
- // Set font characteristics
- SetFontParams();
-
- // Actually draw the strings
- ::MoveTo(0, mFontInfo->ascent + (offsetBy < 0 ? -offsetBy : 0));
- ::DrawString(nameStringToDraw);
- ::MoveTo(sizeName.h, (mFontInfo->ascent + offsetBy));
- ::DrawString(valueStringToDraw);
-
- // After drawing the image, unlock the offscreen buffer in memory
- // and set the port and device back to the original
- ::HUnlock((Handle)mPixMap);
- ::UnlockPixels( mPixMap );
- ::SetGWorld( currentPort, currentDevice );
-
- // set the current state so we don't re-render
- mRenderState = renderON;
- }
-
- // error handling
- catch ( CTickerError &tickerError )
- {
- tickerError.HandleError();
- }
- }
- else if ( renderState == renderOFF ) // (it's OK to set renderOFF repeatedly)
- {
- // unrender anything that we don't need right now, so that
- // we optimize for memory.
- if ( mGWorld )
- {
- ::DisposeGWorld( mGWorld );
- mGWorld = NULL;
- mPixMap = NULL;
- mRenderState = renderOFF;
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::EraseImage
- //
-
- void CTick::EraseImage()
- {
- ASSERT(mPixMap != NULL, "CTick::EraseImage: Null pixmap!");
-
- // Erase the PixMap's bounding box in the GWorld.
- ::EraseRect( &((**mPixMap).bounds) );
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::SetFontParams
- //
-
- void CTick::SetFontParams()
- {
- // a future hook for actual PARAMs
- ::TextFace(bold);
- ::TextFont(applFont);
- ::TextSize(9);
- ::TextMode(srcCopy);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::SaveFontParams
- //
-
- void CTick::SaveFontParams()
- {
- /*
- m_SavedFontParams.textFace = qd.thePort->txFace;
- m_SavedFontParams.textFont = qd.thePort->txFont;
- m_SavedFontParams.textSize = qd.thePort->txSize;
- m_SavedFontParams.textMode = qd.thePort->txMode;
- */
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::ResetFontParams
- //
-
- void CTick::ResetFontParams()
- {
- /*
- TextFace(m_SavedFontParams.textFont);
- TextFont(m_SavedFontParams.textFace);
- TextSize(m_SavedFontParams.textSize);
- TextMode(m_SavedFontParams.textMode);
- */
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::GetTextSize
- //
-
- void CTick::GetTextSize(const StringPtr aString, Point * textSize)
- {
- InitFontInfo();
-
- textSize->v = mFontInfo->ascent + mFontInfo->descent; // compute height
-
- textSize->h = StringWidth(aString); // compute width
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::InitFontInfo
- //
-
- void CTick::InitFontInfo(void)
- {
- if ( mFontInfo == NULL )
- mFontInfo = (FontInfo *) ::CoTaskMemAlloc(sizeof(FontInfo));
-
- if ( mFontInfo == NULL )
- throw CTickerError(FONTINFO_ALLOCATION_ERROR);
-
- SaveFontParams(); // save off the current params
- SetFontParams(); // set the new info in the CURRENT grafport!
-
- ::GetFontInfo(mFontInfo);
-
- ResetFontParams(); // set everything back
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::GetBitMap
- //
-
- BitMap * CTick::GetBitMap(void)
- {
- ASSERT((mPixMap != NULL), "CTick::GetBitMap: NULL pixMap!");
- ::LockPixels( mPixMap );
- ::HLock((Handle)mPixMap);
- BitMap * theBitMap = (BitMap *)(*mPixMap);
- ASSERT((theBitMap != NULL), "NULL bitmap!");
- return theBitMap;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::ReleaseBitMap
- //
-
- void CTick::ReleaseBitMap(void)
- {
- ASSERT((mPixMap != NULL), "NULL pixMap!");
- ::HUnlock((Handle)mPixMap);
- ::UnlockPixels( mPixMap );
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::SetName
- //
-
- char * CTick::SetName(char * name)
- {
- if ( mStrName )
- {
- ::CoTaskMemFree(mStrName);
- mStrName = NULL;
- }
-
- if ( name )
- {
- short length = strlen(name);
- if ( length > MAX_STR_NAME_LENGTH )
- length = MAX_STR_NAME_LENGTH;
-
- mStrName = (char *) ::CoTaskMemAlloc(length+1); // +1 for null term
- if ( mStrName == NULL )
- throw CTickerError(TICK_NAME_ALLOCATION_ERROR, this);
- strncpy(mStrName, name, length);
- mStrName[length] = 0; // null term
- }
-
- return mStrName;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::SetValue
- //
-
- char * CTick::SetValue(char * value)
- {
- if ( mStrValue )
- {
- ::CoTaskMemFree(mStrValue);
- mStrValue = NULL;
- }
-
- if ( value )
- {
- short length = strlen(value) + 1; // +1 for extra space at end
- if ( length > MAX_STR_NAME_LENGTH )
- length = MAX_STR_NAME_LENGTH;
-
- mStrValue = (char *) ::CoTaskMemAlloc(length+1); // +1 for null term
- if ( mStrName == NULL )
- throw CTickerError(TICK_VALUE_ALLOCATION_ERROR, this);
- strncpy(mStrValue, value, length-1);
- strcat(mStrValue, " "); // extra space that we may remove with TruncateValue
- mStrValue[length] = 0; // null term
- }
-
- return mStrValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CTick::SetValue
- //
-
- void CTick::TruncateValue(short numberOfCharacters)
- {
- short len = strlen(mStrValue);
- if ( mStrValue && len > numberOfCharacters )
- mStrValue[len-numberOfCharacters] = 0;
- }
-