home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 28.6 KB | 947 lines | [TEXT/CWIE] |
- //========================================================================================
- //
- // File: View.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #ifndef VIEW_H
- #include "View.h"
- #endif
-
- #ifndef PART_H
- #include "Part.h"
- #endif
-
- #ifndef DEFINES_K
- #include "Defines.k"
- #endif
-
- #ifndef CONTENT_H
- #include "Content.h"
- #endif
-
- #ifndef FRAME_H
- #include "Frame.h"
- #endif
-
- // ----- Part Layer -----
-
- #ifndef FWUTIL_H
- #include "FWUtil.h"
- #endif
-
- #ifndef FWITERS_H
- #include "FWIters.h"
- #endif
-
- #ifndef FWCONTXT_H
- #include "FWContxt.h"
- #endif
-
- #ifndef FWGROWBX_H
- #include "FWGrowBx.h"
- #endif
-
- // ----- OS Layer -----
-
- #ifndef FWTXTSHP_H
- #include "FWTxtShp.h"
- #endif
-
- #ifndef FWRECSHP_H
- #include "FWRecShp.h"
- #endif
-
- #ifndef FWLINSHP_H
- #include "FWLinShp.h"
- #endif
-
- #ifndef FWOVLSHP_H
- #include "FWOvlShp.h"
- #endif
-
- #ifndef FWODGEOM_H
- #include "FWODGeom.h"
- #endif
-
- #ifndef FWTXTBOX_H
- #include "FWTxtBox.h"
- #endif
-
- #ifndef FWCFMRES_H
- #include "FWCFMRes.h"
- #endif
-
- #ifndef FWRESACC_H
- #include "FWResAcc.h"
- #endif
-
- #ifndef FWRESTYP_H
- #include "FWResTyp.h"
- #endif
-
- #ifndef FWFXMATH_H
- #include "FWFxMath.h"
- #endif
-
- #ifndef FWSCRCON_H
- #include "FWScrCon.h"
- #endif
-
- #ifndef FWBITMAP_H
- #include "FWBitmap.h"
- #endif
-
- #ifndef FWBMPSHP_H
- #include "FWBmpShp.h"
- #endif
-
- #ifndef FWARCSHP_H
- #include "FWArcShp.h"
- #endif
-
- #ifndef FWGRUTIL_H
- #include "FWGrUtil.h"
- #endif
-
- #ifndef FWRESTYP_H
- #include "FWResTyp.h"
- #endif
-
- //========================================================================================
- // RunTime information
- //========================================================================================
-
- #ifdef FW_BUILD_MAC
- #pragma segment odfclock
- #endif
-
- //========================================================================================
- // Constants
- //========================================================================================
-
- const FW_Fixed kClockRadius = FW_IntToFixed(1000); // In logical units
- const FW_Fixed kFxPI = FW_DoubleToFixed(3.1415926);
- const FW_Fixed kUsedShapeInset = FW_DoubleToFixed(-0.003);
-
- //========================================================================================
- // class CClockView
- //========================================================================================
-
- FW_DEFINE_AUTO(CClockView)
- FW_DEFINE_CLASS_M1(CClockView, FW_CView)
-
- //----------------------------------------------------------------------------------------
- // CClockView::CClockView
- //----------------------------------------------------------------------------------------
-
- CClockView::CClockView(Environment* ev) :
- FW_CView(ev),
- fClockFrame(NULL),
- fLastTime(FW_CTime::GetCurrentTime())
- {
- SetResizeInvalidates(ev, true);
-
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // CClockView::CClockView
- //----------------------------------------------------------------------------------------
-
- CClockView::~CClockView()
- {
- FW_START_DESTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // CClockView::PostCreateViewFromStream
- //----------------------------------------------------------------------------------------
-
- void CClockView::PostCreateViewFromStream(Environment *ev)
- {
- FW_CView::PostCreateViewFromStream(ev);
-
- fClockFrame = (CClockFrame*)GetFrame(ev);
- fLastTime += fClockFrame->GetClockContent(ev)->GetTimeOffset();
- }
-
- //----------------------------------------------------------------------------------------
- // CClockView::UpdateClock
- //----------------------------------------------------------------------------------------
-
- void CClockView::UpdateClock(Environment* ev, const FW_CTime& time)
- {
- fLastTime = time;
-
- FW_CFrameFacetIterator facets(ev, this->GetFrame(ev));
- for (ODFacet* clockFacet = facets.First(ev); facets.IsNotComplete(ev); clockFacet = facets.Next(ev))
- {
- Draw(ev, clockFacet, FW_CAcquiredODShape(GetFrame(ev)->AcquireUsedShape(ev, NULL)));
- }
- }
-
- //========================================================================================
- // class CAnalogView
- //========================================================================================
-
- FW_DEFINE_AUTO(CAnalogView)
- FW_DEFINE_CLASS_M1(CAnalogView, CClockView)
-
- const FW_ClassTypeConstant LAnalogView = FW_TYPE_CONSTANT('A','N','V','W');
- FW_REGISTER_ARCHIVABLE_CLASS(LAnalogView, CAnalogView, CAnalogView::Create, FW_CView::Read, CAnalogView::Destroy, FW_CView::Write)
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::CAnalogView
- //----------------------------------------------------------------------------------------
-
- CAnalogView::CAnalogView(Environment* ev) :
- CClockView(ev)
- {
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::~CAnalogView
- //----------------------------------------------------------------------------------------
-
- CAnalogView::~CAnalogView()
- {
- FW_START_DESTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FixedCosine
- //----------------------------------------------------------------------------------------
-
- static FW_Fixed FixedCosine(FW_Fixed angleRadians)
- {
- #if (GENERATING68K)
- FW_Fixed hackResult;
- hackResult.fRep = ::Frac2Fix(FracCos(angleRadians.fRep));
- return hackResult;
- #else
- return FW_Cos(angleRadians);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FixedSine
- //----------------------------------------------------------------------------------------
-
- static FW_Fixed FixedSine(FW_Fixed angleRadians)
- {
- #if (GENERATING68K)
- FW_Fixed hackResult;
- hackResult.fRep = ::Frac2Fix(FracSin(angleRadians.fRep));
- return hackResult;
- #else
- return FW_Sin(angleRadians);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::GetTickColor
- //----------------------------------------------------------------------------------------
-
- static void GetTickColor(const FW_CColor& backgroundColor, FW_CColor& color)
- {
- color = backgroundColor;
-
- if(color.IsDarkerThan(FW_CColor(FW_kRGBGray)))
- color += 0x40; // make it brighter
- else
- color -= 0x40; // make it darker
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::GetHoursColor - Get the color of the hours hand
- //----------------------------------------------------------------------------------------
-
- static void GetHoursColor(const FW_CColor& backgroundColor, FW_CColor& color)
- {
- color = backgroundColor;
-
- if(color.IsDarkerThan(FW_CColor(FW_kRGBGray)))
- color += 0x40; // make it brighter
- else
- color -= 0x40; // make it darker
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::GetMinutesColor - Get the color of the minutes hand
- //----------------------------------------------------------------------------------------
-
- static void GetMinutesColor(const FW_CColor& backgroundColor, FW_CColor& color)
- {
- GetHoursColor(backgroundColor, color);
-
- if(backgroundColor.IsDarkerThan(FW_CColor(FW_kRGBGray)))
- color += 0x40; // make it brighter
- else
- color -= 0x40; // make it darker
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::GetSecondsColor - Get the color of the seconds hand
- //----------------------------------------------------------------------------------------
-
- static void GetSecondsColor(const FW_CColor& backgroundColor, FW_CColor& color)
- {
- if(backgroundColor.IsDarkerThan(FW_CColor(FW_kRGBGray)))
- color = FW_kRGBWhite;
- else
- color = FW_kRGBBlack;
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::DoUpdateClockFacet
- //----------------------------------------------------------------------------------------
-
- void CAnalogView::DoUpdateClockFacet(Environment* ev,
- FW_CGraphicContext* gc,
- const FW_CRect& clockRect,
- const FW_CTime& newTime)
- {
- FW_UNUSED(ev);
- FW_UNUSED(clockRect); // this is not in clock coordinates
-
- FW_CRect clockBox(-kClockRadius, -kClockRadius, kClockRadius, kClockRadius);
-
- FW_CColor backGroundColor;
- fClockFrame->GetBackgroundColor(&backGroundColor);
-
- // erase the background
- FW_CRectShape::RenderRect(*gc, clockBox, FW_kFill, backGroundColor);
-
- // and draw it
- this->DrawClockFace(ev, gc);
-
- this->DrawHourHand(ev, gc, FW_IntToFixed(newTime.GetHour()), FW_IntToFixed(newTime.GetMinute()));
- this->DrawMinuteHand(ev, gc, FW_IntToFixed(newTime.GetMinute()));
- this->DrawSecondHand(ev, gc, FW_IntToFixed(newTime.GetSecond()));
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::Draw
- //----------------------------------------------------------------------------------------
-
- void CAnalogView::Draw(Environment *ev, ODFacet* odFacet, ODShape* invalidShape)
- {
- ODCanvas* canvas = odFacet->GetCanvas(ev);
-
- FW_CAcquiredODShape aqUsedShape(GetFrame(ev)->AcquireUsedShape(ev, NULL));
- FW_CRect clockBox = FW_GetShapeBoundingBox(ev, aqUsedShape);
-
- FW_CMapping mapping(FW_kCustomConstrained);
- FW_CPoint logicalExtent(FW_MultipliedByInt(kClockRadius, 2), FW_MultipliedByInt(kClockRadius, 2));
-
- FW_CAcquiredODTransform aqExternalTransform = odFacet->AcquireExternalTransform(ev, NULL);
-
- if( ! canvas->IsDynamic(ev) ) // we only draw offscreen when drawing to a dynamic canvas
- {
- FW_CViewContext vc(ev, this, odFacet, invalidShape);
-
- FW_CPoint deviceExtent(GetExtent(ev));
-
- mapping.SetExtents(ev, logicalExtent, deviceExtent);
-
- mapping.SetDeviceOrigin(ev, FW_Half(deviceExtent.x), FW_Half(deviceExtent.y));
-
- vc.SetMapping(mapping);
-
- DoUpdateClockFacet(ev, &vc, clockBox, fLastTime);
- }
- else
- {
- // The offscreen business for the analog view is different.
- // the logical space (in which all drawing is performed) is
- // fixed (-kClockRadius, -kClockRadius, kClockRadius, kClockRadius)
- // while the physical (or device) space is the actual offscreen size,
- // which is based on the used shape.
-
- FW_CPoint deviceExtent(clockBox.Width(), clockBox.Height());
-
- // create an offscreen bitmap
- FW_CBitmap bits(FW_FixedToInt(deviceExtent.x), FW_FixedToInt(deviceExtent.y), 0, NULL);
-
- {
- // create a graphics context so that we can draw _to_ the bitmap
- FW_CBitmapContext vc(ev, bits);
-
- // set the logical and physical extents
- mapping.SetExtents(ev, logicalExtent, deviceExtent);
-
- // set the device origin to the center
- mapping.SetDeviceOrigin(ev, FW_Half(deviceExtent.x), FW_Half(deviceExtent.y));
-
- // install the mapping
- vc.SetMapping(mapping);
-
- DoUpdateClockFacet(ev, &vc, clockBox, fLastTime);
-
- // ----- Set the Highlight -----
- if (odFacet->GetHighlight(ev) == kODFullHighlight)
- {
- FW_CRect clockRect(-kClockRadius, -kClockRadius, kClockRadius, kClockRadius);
- FW_CRectShape::RenderRect(vc, clockRect, FW_kFill, FW_CInk(FW_kSystemHilite));
- }
- // the bitmap context is destructed here, but the bits remain
- }
-
- FW_CViewContext vc(ev, this, odFacet, invalidShape);
-
- // render the bitmap
- FW_CBitmapShape::RenderBitmap(vc, bits, clockBox);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::DrawTicks
- //----------------------------------------------------------------------------------------
-
- static void DrawTicks(FW_CGraphicContext* gc, FW_CBoundedShape& tickShape,
- FW_Fixed xPos, FW_Fixed yPos,
- FW_Fixed tickWidth)
- {
- tickWidth = FW_DividedByInt(tickWidth, 2);
-
- tickShape.SetRectangle(FW_CRect(xPos - tickWidth, yPos - tickWidth, xPos + tickWidth, yPos + tickWidth));
- tickShape.Render(*gc);
-
- tickShape.SetRectangle(FW_CRect( - xPos - tickWidth, yPos - tickWidth, - xPos + tickWidth, yPos + tickWidth));
- tickShape.Render(*gc);
-
- tickShape.SetRectangle(FW_CRect(xPos - tickWidth, - yPos - tickWidth, xPos + tickWidth, - yPos + tickWidth));
- tickShape.Render(*gc);
-
- tickShape.SetRectangle(FW_CRect( - xPos - tickWidth, - yPos - tickWidth, - xPos + tickWidth, - yPos + tickWidth));
- tickShape.Render(*gc);
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::DrawClockFace
- //----------------------------------------------------------------------------------------
-
- void CAnalogView::DrawClockFace(Environment* ev, FW_CGraphicContext* gc)
- {
- FW_UNUSED(ev);
- // ----- Erase under the clock -----
- FW_CRect ovalRect(-kClockRadius, -kClockRadius, kClockRadius, kClockRadius);
-
- FW_CColor backGroundColor;
- fClockFrame->GetBackgroundColor(&backGroundColor);
-
- FW_CColor tickColor;
- GetTickColor(backGroundColor, tickColor);
-
- FW_CColor rimColor;
- if(backGroundColor.IsDarkerThan(FW_CColor(FW_kRGBGray)))
- rimColor = FW_kRGBWhite;
- else
- rimColor = FW_kRGBBlack;
-
- FW_COvalShape::RenderOval(
- *gc,
- ovalRect,
- FW_kFrame,
- rimColor,
- FW_CStyle(kClockRadius * FW_DoubleToFixed(0.02)));
-
- // ----- Render the "ODF" string -----
-
- FW_CString faceString = fClockFrame->GetClockContent(ev)->GetFaceString();
-
- FW_CTextShape::RenderText(
- *gc,
- faceString,
- FW_CPoint(FW_IntToFixed(0), - FW_Half(kClockRadius)),
- FW_CFont(FW_GetHelveticaFontName(), FW_kItalic, FW_DividedByInt(kClockRadius, 5)),
- FW_kTextAlignHCenter | FW_kTextAlignBaseLine, FW_CInk(tickColor, FW_kRGBWhite, FW_kOr));
-
-
- // ----- Render the ticks around the clock face -----
-
- // create a rectangle shape for the small ticks
- FW_CRectShape rectShape;
- rectShape.SetInk(FW_CInk(tickColor));
-
- // create an oval shape for the large ticks
- FW_COvalShape ovalShape(ovalRect, FW_kFill);
- ovalShape.SetInk(FW_CInk(tickColor));
-
- // Use the symmetry of the clock face to speed up the calculations for drawing the face
- // We only need to calculate points for 45 degrees of the circle. The remaining points can
- // be inferred from these points
-
- short angle = 0;
- short fiveMinute = 0;
-
- while (angle < 45)
- {
- // ----- convert angle to radians -----
- FW_Fixed radians = FW_DividedByInt(kFxPI * FW_IntToFixed(90 - angle), 180);
- FW_Fixed cosRadian = FixedCosine(radians);
- FW_Fixed sinRadian = FixedSine(radians);
-
- FW_Fixed tickRadius = kClockRadius * FW_DoubleToFixed(0.9);
- FW_Fixed xTick = tickRadius * cosRadian;
- FW_Fixed yTick = tickRadius * sinRadian;
-
- if(fiveMinute == 0)
- {
- fiveMinute = 4;
-
- FW_Fixed tickWidth = FW_DividedByInt(kClockRadius, 15);
-
- DrawTicks(gc, ovalShape, xTick, yTick, tickWidth);
-
- DrawTicks(gc, ovalShape, yTick, xTick, tickWidth);
- }
- else
- {
- fiveMinute--;
-
- FW_Fixed tickWidth = FW_DividedByInt(kClockRadius, 30);
-
- DrawTicks(gc, rectShape, xTick, yTick, tickWidth);
-
- DrawTicks(gc, rectShape, yTick, xTick, tickWidth);
- }
-
- angle += 6; // a tick occurs every six degrees
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CalcPoint
- //----------------------------------------------------------------------------------------
-
- static FW_CPoint CalcPoint(FW_Fixed radius, FW_Fixed angle)
- {
- return FW_CPoint(
- radius * FixedSine(angle),
- - radius * FixedCosine(angle));
- }
-
- //----------------------------------------------------------------------------------------
- // ::DegreesToRadians
- //----------------------------------------------------------------------------------------
-
- static inline FW_Fixed DegreesToRadians(FW_Fixed degrees)
- {
- return FW_DividedByInt(degrees * kFxPI, 180);
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::DrawHourHand
- //----------------------------------------------------------------------------------------
-
- void CAnalogView::DrawHourHand(Environment* ev,
- FW_CGraphicContext* gc,
- FW_Fixed hour,
- FW_Fixed minute)
- {
- FW_UNUSED(ev);
- FW_Fixed hourRadius = kClockRadius * FW_DoubleToFixed(0.5); // Make the hour hand short
-
- if (hour > FW_IntToFixed(11))
- hour -= FW_IntToFixed(12);
-
- // ----- Divide the clock face into degrees.
- // ----- Hour hand falls on every five minutes or every 30 degrees
- FW_Fixed clockDegrees = FW_MultipliedByInt(hour, 30) + FW_Half(minute);
- FW_Fixed radians = ::DegreesToRadians(clockDegrees);
-
- // calculate the point where the tip of the hand should end
- FW_CPoint newPoint = ::CalcPoint(hourRadius, radians);
-
- const short arcDegrees = 14; // the hand is a filled arc this many degrees wide
- // adjust angle so the base of the arc is centered
- short angle = FW_FixedToInt(clockDegrees) - (arcDegrees / 2);
-
- // flip it to the other side
- angle += 180;
-
- FW_CRect faceRect(-hourRadius, -hourRadius, hourRadius, hourRadius);
-
- // offset the reference rectangle so the center is where we want the vertex of the arc
- faceRect.Offset(newPoint.x, newPoint.y);
-
-
- FW_CColor backGroundColor;
- fClockFrame->GetBackgroundColor(&backGroundColor);
-
- FW_CColor color;
- GetHoursColor(backGroundColor, color);
-
- FW_CArcShape::RenderArc(*gc, faceRect,
- angle,
- arcDegrees,
- FW_kFill,
- color);
-
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::DrawMinuteHand
- //----------------------------------------------------------------------------------------
-
- void CAnalogView::DrawMinuteHand(Environment* ev,
- FW_CGraphicContext* gc,
- FW_Fixed minute)
- {
- FW_UNUSED(ev);
- FW_Fixed minuteRadius = kClockRadius * FW_DoubleToFixed(0.8); // Make the minute hand longer than the hour hand
-
- // ----- Divide the clock face into degrees.
- // ----- (360 degrees divided by 60 minutes is 6 degrees per minute)
- FW_Fixed clockDegrees = FW_MultipliedByInt(minute, 6);
- FW_Fixed radians = ::DegreesToRadians(clockDegrees);
-
- FW_CPoint newPoint = ::CalcPoint(minuteRadius, radians);
-
- const short arcDegrees = 6; // the hand is a filled arc this many degrees wide
- // adjust angle so the base of the arc is centered
- short angle = FW_FixedToInt(clockDegrees) - (arcDegrees / 2);
-
- // flip it to the other side
- angle += 180;
-
- FW_CRect faceRect(-minuteRadius, -minuteRadius, minuteRadius, minuteRadius);
-
- // offset the reference rectangle so the center is where we want the vertex of the arc
- faceRect.Offset(newPoint.x, newPoint.y);
-
- FW_CColor backGroundColor;
- fClockFrame->GetBackgroundColor(&backGroundColor);
-
- FW_CColor color;
- GetMinutesColor(backGroundColor, color);
-
- FW_CArcShape::RenderArc(*gc, faceRect,
- angle,
- arcDegrees,
- FW_kFill,
- color);
-
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::DrawSecondHand
- //----------------------------------------------------------------------------------------
-
- void CAnalogView::DrawSecondHand(Environment* ev,
- FW_CGraphicContext* gc,
- FW_Fixed second)
- {
- FW_UNUSED(ev);
- FW_Fixed secondRadius = kClockRadius * FW_DoubleToFixed(0.9); // A nice sweeping second hand
-
- // ----- Divide the clock face into degrees.
- // ----- (360 degrees divided by 60 seconds is 6 degrees per second)
- FW_Fixed radians = ::DegreesToRadians(FW_MultipliedByInt(second, 6));
-
- FW_CPoint newPoint = ::CalcPoint(secondRadius, radians);
-
- FW_CLineShape lineShape(FW_kZeroPoint, newPoint);
- FW_CColor backGroundColor;
- fClockFrame->GetBackgroundColor(&backGroundColor);
-
- FW_CColor color;
- GetSecondsColor(backGroundColor, color);
-
- lineShape.SetInk(FW_CInk(color));
- lineShape.Render(*gc);
-
- // draw a "pin" in the center
- FW_Fixed pinRadius = FW_DividedByInt(kClockRadius, 40);
- FW_CRect pinRect(-pinRadius, -pinRadius, pinRadius, pinRadius);
- FW_COvalShape::RenderOval(*gc, pinRect, FW_kFill, color);
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::CreateUsedShape
- //----------------------------------------------------------------------------------------
-
- ODShape* CAnalogView::CreateUsedShape(Environment* ev, const FW_CRect& suggestedUsedRect)
- {
- FW_CRect rect(suggestedUsedRect);
- FW_Fixed height = suggestedUsedRect.Height();
- FW_Fixed width = suggestedUsedRect.Width();
-
- if (height < width)
- rect.right = rect.left + height;
- else
- rect.bottom = rect.top + width;
-
- rect.PlaceInCenterOf(suggestedUsedRect);
-
- return ::FW_CreateOvalODShape(ev, rect);
- }
-
- //----------------------------------------------------------------------------------------
- // CAnalogView::Create
- //----------------------------------------------------------------------------------------
-
- void* CAnalogView::Create(FW_CReadableStream& stream, FW_ClassTypeConstant type)
- {
- FW_UNUSED(stream);
- FW_UNUSED(type);
- FW_SOMEnvironment ev;
- return FW_NEW(CAnalogView, (ev));
- }
-
- //----------------------------------------------------------------------------------------
- // CDrawView::Destroy
- //----------------------------------------------------------------------------------------
-
- void CAnalogView::Destroy(void* object, FW_ClassTypeConstant type)
- {
- FW_UNUSED(type);
- CAnalogView* self = (CAnalogView*) object;
- delete self;
- }
-
- //========================================================================================
- // class CDigitalView
- //========================================================================================
-
- FW_DEFINE_AUTO(CDigitalView)
- FW_DEFINE_CLASS_M1(CDigitalView, CClockView)
-
- const FW_ClassTypeConstant LDigitalView = FW_TYPE_CONSTANT('D','G','V','W');
- FW_REGISTER_ARCHIVABLE_CLASS(LDigitalView, CDigitalView, CDigitalView::Create, FW_CView::Read, CDigitalView::Destroy, FW_CView::Write)
-
-
- //----------------------------------------------------------------------------------------
- // CDigitalView::CDigitalView
- //----------------------------------------------------------------------------------------
-
- CDigitalView::CDigitalView(Environment* ev) :
- CClockView(ev),
- fFont(FW_kCourier12)
- {
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // CDigitalView::~CDigitalView
- //----------------------------------------------------------------------------------------
-
- CDigitalView::~CDigitalView()
- {
- FW_START_DESTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // CDigitalView::GetDigitalClockRect
- //----------------------------------------------------------------------------------------
-
- FW_CRect CDigitalView::GetDigitalClockRect(Environment* ev, const FW_CRect& suggestedUsedRect)
- {
- // ----- Calculate a default rectangle size for a digital clock
- FW_CString32 digitalString;
- {
- FW_PSharedLibraryResourceFile resFile(ev);
- ::FW_LoadStringByID(ev, resFile, kClockFaceStrings, FW_kMultiStringRes, kClockDigitalWidthString, digitalString);
- }
-
- FW_CTextShape textShape(digitalString,
- FW_IntToFixed(0),
- FW_IntToFixed(0),
- fFont);
-
- FW_CScreenContext sc(ev); // we need a context for measuring the text
-
- short boxHeight = FW_FixedToInt(suggestedUsedRect.Height());
- short boxWidth = FW_FixedToInt(suggestedUsedRect.Width());
- short fontSize = boxHeight;
- FW_CRect boundsRect;
-
- for(;;)
- {
- fFont.SetFontSize(FW_IntToFixed(fontSize));
- FW_CFontMetrics metrics;
- fFont.GetFontMetrics(sc, metrics);
- short fontHeight = metrics.GetFontHeight();
- if(fontHeight > boxHeight)
- {
- fontSize = ( (long) fontSize * boxHeight) / fontHeight;
- }
- else
- {
- textShape.GetBounds(sc, boundsRect);
- short textWidth = FW_FixedToInt(boundsRect.Width());
- if(boxWidth < textWidth)
- fontSize = ( (long) fontSize * boxWidth) / textWidth;
- else
- {
- break;
- }
- }
-
- if(fontSize == 0) // punt
- {
- fFont.SetFontSize(FW_IntToFixed(12));
- textShape.GetBounds(sc, boundsRect);
- break;
- }
- }
-
- boundsRect.PlaceInCenterOf(suggestedUsedRect);
-
- return boundsRect;
- }
-
- //----------------------------------------------------------------------------------------
- // CDigitalView::DoUpdateClockFacet
- //----------------------------------------------------------------------------------------
-
- void CDigitalView::DoUpdateClockFacet(Environment* ev,
- FW_CGraphicContext* gc,
- const FW_CRect& clockRect,
- const FW_CTime& newTime)
- {
- FW_UNUSED(ev);
- FW_CString255 timeString;
- newTime.GetTimeString(timeString, TRUE);
-
- FW_CColor backGroundColor;
- fClockFrame->GetBackgroundColor(&backGroundColor);
-
- FW_CColor contrastColor;
- if(backGroundColor.IsDarkerThan(FW_CColor(FW_kRGBGray)))
- contrastColor = FW_kRGBWhite;
- else
- contrastColor = FW_kRGBBlack;
-
- FW_CRectShape::RenderRect(*gc, clockRect, FW_kFill, backGroundColor);
- FW_CRectShape::RenderRect(*gc, clockRect, FW_kFrame, contrastColor);
-
- FW_CTextShape::RenderText(*gc, timeString, clockRect.Center(), fFont,
- FW_kTextAlignHCenter | FW_kTextAlignVCenter,
- FW_CInk(contrastColor, FW_kRGBWhite, FW_kOr));
- }
-
- //----------------------------------------------------------------------------------------
- // CDigitalView::Draw
- //----------------------------------------------------------------------------------------
-
- void CDigitalView::Draw(Environment* ev, ODFacet* odFacet, ODShape* invalidShape)
- {
- ODCanvas* canvas = odFacet->GetCanvas(ev);
-
- FW_CAcquiredODShape aqUsedShape(GetFrame(ev)->AcquireUsedShape(ev, NULL));
- FW_CRect clockBox = FW_GetShapeBoundingBox(ev, aqUsedShape);
- clockBox.Inset(kClockRadius * -kUsedShapeInset, kClockRadius * -kUsedShapeInset);
-
- if( ! canvas->IsDynamic(ev) ) // we only draw offscreen when drawing to a dynamic canvas
- {
- FW_CViewContext vc(ev, this, odFacet, invalidShape);
-
- DoUpdateClockFacet(ev, &vc, clockBox, fLastTime);
- }
- else
- {
- // Different from the analog view, the digital view's extent is
- // the same as the offscreen device, but we have to fiddle with the origin
- // because the offscreen has a default origin of (0,0)
-
- // create an offscreen bitmap
- FW_CBitmap bits(FW_FixedToInt(clockBox.Width()), FW_FixedToInt(clockBox.Height()), 0, NULL);
-
- {
- // create a graphics context so that we can draw _to_ the bitmap
- FW_CBitmapContext vc(ev, bits);
-
- // because the mapping of the bitmap has its origin at 0, and the
- // used shape bounds upon which DoUpdateClockFacet bases its mapping
- // is probably not at 0, 0, we change the logical mapping so that the clock
- // draws in the right spot.
- FW_CMapping mapping;
- vc.GetMapping(mapping);
- mapping.SetLogicalOrigin(ev, clockBox.left, clockBox.top);
- vc.SetMapping(mapping);
-
- // we don't need to prepare the offscreen since DoUpdateClockFacet
- // will paint the whole image. Otherwise...
- // FW_CRectShape::RenderRect(vc, box, FW_kFill, FW_kRGBWhite);
-
- DoUpdateClockFacet(ev, &vc, clockBox, fLastTime);
-
- // ----- Set the Highlight -----
- if (odFacet->GetHighlight(ev) == kODFullHighlight)
- FW_CRectShape::RenderRect(vc, clockBox, FW_kFill, FW_CInk(FW_kSystemHilite));
-
- // the bitmap context is destructed here, but the bits remain
- }
-
- FW_CViewContext vc(ev, this, odFacet, invalidShape);
-
- // render the bitmap
- FW_CBitmapShape::RenderBitmap(vc, bits, clockBox);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CDigitalView::CreateUsedShape
- //----------------------------------------------------------------------------------------
-
- ODShape* CDigitalView::CreateUsedShape(Environment* ev, const FW_CRect& suggestedUsedRect)
- {
- FW_CRect rect = GetDigitalClockRect(ev, suggestedUsedRect);
-
- rect.Inset(kClockRadius * kUsedShapeInset, kClockRadius * kUsedShapeInset);
-
- // Below shows two equivalent methods for specifying the used shape, the first
- // as a region, and the second as an ODPolygon with one contour.
-
- // The first method is not likely to fail, so the second method will probably never
- // get used. It's here as an example. [BRP]
-
- const short kCorners = 4;
- FW_CPoint rectCorners[kCorners] = {
- FW_CPoint(rect.left, rect.top),
- FW_CPoint(rect.right, rect.top),
- FW_CPoint(rect.right, rect.bottom),
- FW_CPoint(rect.left, rect.bottom)
- };
-
- ODShape *shape = ::FW_CreatePolygonODShape(ev, kCorners, rectCorners);
-
- if(shape == NULL)
- shape = ::FW_NewODShape(ev, rect);
-
- return shape;
- }
-
- //----------------------------------------------------------------------------------------
- // CDigitalView::Create
- //----------------------------------------------------------------------------------------
-
- void* CDigitalView::Create(FW_CReadableStream& stream, FW_ClassTypeConstant type)
- {
- FW_UNUSED(stream);
- FW_UNUSED(type);
-
- FW_SOMEnvironment ev;
- return FW_NEW(CDigitalView, (ev));
- }
-
- //----------------------------------------------------------------------------------------
- // CDigitalView::Destroy
- //----------------------------------------------------------------------------------------
-
- void CDigitalView::Destroy(void* object, FW_ClassTypeConstant type)
- {
- FW_UNUSED(type);
-
- CDigitalView* self = (CDigitalView*) object;
- delete self;
- }
-
-