home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-08-16 | 18.0 KB | 616 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: Frame.cpp
- // Release Version: $ ODF 1 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #ifndef FRAME_H
- #include "Frame.h"
- #endif
-
- #ifndef PART_H
- #include "Part.h"
- #endif
-
- #ifndef DEFINES_K
- #include "Defines.k"
- #endif
-
- #ifndef CONTENT_H
- #include "Content.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
-
- #ifndef FWSCLBAR_H
- #include "FWSclBar.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
-
- //========================================================================================
- // RunTime information
- //========================================================================================
-
- #ifdef FW_BUILD_MAC
- #pragma segment odfclock
- #endif
-
- //========================================================================================
- // Constants
- //========================================================================================
-
- const FW_Fixed kClockRadius = FW_IntToFixed(100); // In logical units
- const FW_Fixed kFxPI = FW_DoubleToFixed(3.1415926);
-
- //========================================================================================
- // class CClockFrame
- //========================================================================================
-
- FW_DEFINE_AUTO(CClockFrame)
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::CClockFrame
- //----------------------------------------------------------------------------------------
-
- CClockFrame::CClockFrame(Environment* ev, ODFrame* odFrame,
- FW_CPresentation* presentation,
- CClockPart* clockPart,
- CClockContent* clockContent) :
- FW_CFrame(ev, odFrame, presentation, clockPart),
- fMapping(FW_kCustomConstrained),
- fDigitalFont(FW_kSystemFont, FW_kPlain, FW_IntToFixed(12)),
- fClockContent(clockContent),
- fClockPart(clockPart),
- fLastTime(FW_CTime::GetCurrentTime())
- {
- // ----- Load the face string ("OpenDoc") -----
- {
- FW_CSharedLibraryResourceFile resFile(ev);
- ::FW_LoadStringByID(ev, resFile, kClockFaceStrings, MULTISTRINGRES, kClockOpenDocString, fFaceString);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::~CClockFrame
- //----------------------------------------------------------------------------------------
-
- CClockFrame::~CClockFrame()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::FacetAdded
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::FacetAdded(Environment* ev, ODFacet* facet, unsigned short facetCount)
- {
- FW_CFrame::FacetAdded(ev, facet, facetCount);
-
- if (facetCount == 1)
- {
- // ----- First reset the mapping. Because ResetMapping needs the window
- // ----- we have to wait for FacetAdded before calling ResetMapping the first time
- this->ResetMapping(ev);
-
- this->UpdateUsedAndActiveShapes(ev);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::GetDigitalClockRect
- //----------------------------------------------------------------------------------------
-
- FW_CRect CClockFrame::GetDigitalClockRect(Environment* ev)
- {
- // ----- Calculate a default rectangle size for a digital clock
- FW_CString32 digitalString;
- {
- FW_CSharedLibraryResourceFile resFile(ev);
- ::FW_LoadStringByID(ev, resFile, kClockFaceStrings, MULTISTRINGRES, kClockDigitalWidthString, digitalString);
- }
-
- FW_CTextShape textShape(digitalString,
- FW_IntToFixed(0),
- FW_IntToFixed(0),
- fDigitalFont,
- FW_kTextAlignLeft | FW_kTextAlignBaseLine);
-
-
- FW_CScreenContext sc(ev);
-
- FW_CRect rect;
- textShape.GetBounds(sc, rect);
-
- rect.Inset(FW_IntToFixed(-3), FW_IntToFixed(-3));
-
- return rect;
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::ChangeClockType
- //----------------------------------------------------------------------------------------
- // If I switch to analog and my frame is smaller than ff(80) try to request something bigger
-
- void CClockFrame::ChangeClockType(Environment* ev, short newClockType)
- {
- if (!IsTopFrame(ev) && newClockType == kAnalogClock)
- {
- FW_CRect frameBounds = GetBounds(ev);
- FW_Fixed min = FW_Minimum(frameBounds.Height(), frameBounds.Width());
-
- if (min < FW_IntToFixed(80))
- {
- FW_CAcquiredODShape askedShape = ::FW_NewODShape(ev, FW_CRect(FW_kZeroPoint, FW_IntToFixed(80), FW_IntToFixed(80)));
- this->RequestFrameShape(ev, askedShape);
- }
- }
-
- UpdateUsedAndActiveShapes(ev);
- ResetMapping(ev);
- Invalidate(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::AdjustUsedShape
- //----------------------------------------------------------------------------------------
- // 'suggestedUsedShape' is equal to the frame shape
-
- ODShape* CClockFrame::AdjustUsedShape(Environment* ev, ODShape* suggestedUsedShape)
- {
- if (GetViewType(ev) != FW_CPart::gViewAsFrameToken)
- return FW_CFrame::AdjustUsedShape(ev, suggestedUsedShape);
-
- FW_CRect usedRect = FW_GetShapeBoundingBox(ev, suggestedUsedShape);
-
- ODShape* newUsedShape;
- if (fClockContent->GetClockType() == kAnalogClock)
- {
- FW_CRect rect(usedRect);
- FW_Fixed height = usedRect.Height();
- FW_Fixed width = usedRect.Width();
-
- if (height < width)
- rect.right = rect.left + height;
- else
- rect.bottom = rect.top + width;
- rect.PlaceInCenter(usedRect);
-
- newUsedShape = ::FW_CreateOvalODShape(ev, rect);
- }
- else
- {
-
- FW_CRect rect = GetDigitalClockRect(ev);
- rect.PlaceInCenter(usedRect);
-
- newUsedShape = ::FW_NewODShape(ev, rect);
- }
-
- return newUsedShape;
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::AdjustActiveShape
- //----------------------------------------------------------------------------------------
- // [HLX] Because OpenDoc uses the Frame shape as the default active shape I need to
- // adjust my active shape too.
-
- ODShape* CClockFrame::AdjustActiveShape(Environment* ev, ODFacet* facet, ODShape* suggestedActiveShape)
- {
- if (GetViewType(ev) != FW_CPart::gViewAsFrameToken)
- return FW_CFrame::AdjustActiveShape(ev, facet, suggestedActiveShape);
-
- suggestedActiveShape->Acquire(ev);
- return suggestedActiveShape;
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::FrameShapeChanged
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::FrameShapeChanged(Environment* ev)
- {
- FW_CFrame::FrameShapeChanged(ev);
-
- this->ResetMapping(ev);
- this->Invalidate(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::UpdateClock
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::UpdateClock(Environment* ev, const FW_CTime& time)
- {
- FW_CFrameFacetIterator facets(ev, this);
- for (ODFacet* clockFacet = facets.First(ev); facets.IsNotComplete(ev); clockFacet = facets.Next(ev))
- {
- FW_CViewContext fc(ev, this, clockFacet);
-
- if (fClockContent->GetClockType() == kAnalogClock)
- {
- fc.SetMapping(fMapping);
- UpdateAnalogClock(ev, fc, time);
- }
- else
- UpdateDigitalClock(ev, fc, time);
- }
-
- fLastTime = time;
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::Draw
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::Draw(Environment* ev, ODFacet* odFacet, ODShape* invalidShape)
- {
- FW_CViewContext fc(ev, this, odFacet, invalidShape);
-
- // [HLX] This will be moved into an erase adorner
- if (IsRoot(ev))
- {
- FW_CRect invalidRect;
- fc.GetClipRect(invalidRect);
-
- #ifdef FW_BUILD_MAC
- FW_CInk ink(FW_kRGBWhite,
- FW_kRGBWhite,
- FW_kErase);
- #else
- FW_CInk ink(FW_CColor(::GetSysColor(COLOR_WINDOWTEXT), 0),
- FW_CColor(::GetSysColor(COLOR_APPWORKSPACE), 0),
- FW_kErase);
- #endif
- FW_CRectShape::RenderRect(fc, invalidRect, FW_kFill, ink);
- }
-
- if (fClockContent->GetClockType() == kAnalogClock)
- {
- fc.SetMapping(fMapping);
-
- this->DrawClockFace(ev, fc);
-
- this->DrawSecondHand(ev, fc, FW_IntToFixed(fLastTime.GetSecond()));
- this->DrawMinuteHand(ev, fc, FW_IntToFixed(fLastTime.GetMinute()));
- this->DrawHourHand(ev, fc, FW_IntToFixed(fLastTime.GetHour()), FW_IntToFixed(fLastTime.GetMinute()));
- }
- else
- UpdateDigitalClock(ev, fc, fLastTime);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawTicks
- //----------------------------------------------------------------------------------------
-
- static void DrawTicks(FW_CGraphicContext& gc, FW_CLineShape& lineShape,
- FW_Fixed xStart, FW_Fixed yStart,
- FW_Fixed xEnd, FW_Fixed yEnd)
- {
- lineShape.SetLineStart(xStart, yStart);
- lineShape.SetLineEnd(xEnd, yEnd);
- lineShape.Render(gc);
-
- lineShape.SetLineStart(-xStart, yStart);
- lineShape.SetLineEnd(-xEnd, yEnd);
- lineShape.Render(gc);
-
- lineShape.SetLineStart(xStart, -yStart);
- lineShape.SetLineEnd(xEnd, -yEnd);
- lineShape.Render(gc);
-
- lineShape.SetLineStart(-xStart,-yStart);
- lineShape.SetLineEnd(-xEnd, -yEnd);
- lineShape.Render(gc);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::ResetMapping
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::ResetMapping(Environment* ev)
- {
- FW_CPoint logicalExtent(FW_MultipliedByInt(kClockRadius, 2), FW_MultipliedByInt(kClockRadius, 2));
- FW_CPoint deviceExtent = GetExtent(ev);
-
- fMapping.SetExtents(ev, logicalExtent, deviceExtent);
- fMapping.SetDeviceOrigin(ev, FW_Half(deviceExtent.x), FW_Half(deviceExtent.y));
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawClockFace
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::DrawClockFace(Environment* ev, FW_CGraphicContext& gc)
- {
- // ----- Erase under the clock -----
- FW_CRect ovalRect(-kClockRadius, -kClockRadius, kClockRadius, kClockRadius);
-
- FW_COvalShape::RenderOval(
- gc,
- ovalRect,
- FW_kFill,
- FW_kWhiteEraseInk);
-
- FW_COvalShape::RenderOval(
- gc,
- ovalRect,
- FW_kFrame,
- FW_kNormalInk,
- FW_CStyle(FW_IntToFixed(2)));
-
- // ----- Render the "OpenDoc" string -----
- FW_CTextShape::RenderText(
- gc,
- fFaceString,
- FW_CPoint(FW_IntToFixed(0), - FW_Half(kClockRadius)),
- FW_CFont(FW_kHelvetica, FW_kItalic, FW_DividedByInt(kClockRadius, 5)),
- FW_kTextAlignHCenter | FW_kTextAlignBaseLine);
-
- // 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;
-
- FW_CStyle lineStyle = FW_ODFixedToFixed(0x00008000); // 1/2
- FW_CLineShape lineShape;
- lineShape.SetStyle(lineStyle);
-
- FW_Fixed xStart, yStart, xEnd, yEnd;
-
- FW_Fixed radius = kClockRadius - FW_IntToFixed(2); // 2 logical unit
- while (angle < 45)
- {
- // ----- convert angle to radians -----
- FW_Fixed radians = FW_DividedByInt(kFxPI * FW_IntToFixed(90 - angle), 180);
- FW_Fixed cosRadian = FW_Cos(radians);
- FW_Fixed sinRadian = FW_Sin(radians);
-
- xStart = radius * cosRadian;
- yStart = radius * sinRadian;
-
- FW_Fixed tickRadius;
- if (fiveMinute == 0)
- {
- tickRadius = radius - FW_DividedByInt(radius, 10);
- fiveMinute = 4;
- }
- else
- {
- tickRadius = radius - FW_DividedByInt(radius, 20);
- fiveMinute--;
- }
-
- xEnd = tickRadius * cosRadian;
- yEnd = tickRadius * sinRadian;
-
- DrawTicks(gc, lineShape, xStart, yStart, xEnd, yEnd);
-
- DrawTicks(gc, lineShape, yStart, xStart, yEnd, xEnd);
-
- angle += 6;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CalcPoint
- //----------------------------------------------------------------------------------------
-
- static FW_CPoint CalcPoint(FW_Fixed radius, FW_Fixed angle)
- {
- return FW_CPoint(
- radius * FW_Sin(angle),
- - radius * FW_Cos(angle));
- }
-
- //----------------------------------------------------------------------------------------
- // ::DegreesToRadians
- //----------------------------------------------------------------------------------------
-
- static inline FW_Fixed DegreesToRadians(FW_Fixed degrees)
- {
- return FW_DividedByInt(degrees * kFxPI, 180);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawHourHand
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::DrawHourHand(Environment* ev,
- FW_CGraphicContext& gc,
- FW_Fixed hour,
- FW_Fixed minute)
- {
- FW_Fixed hourRadius = FW_DividedByInt(kClockRadius, 2); // Make the hour hand short and stubby
-
- 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 radians = ::DegreesToRadians(FW_MultipliedByInt(hour, 30) + FW_Half(minute));
-
- FW_CPoint newPoint = ::CalcPoint(hourRadius, radians);
-
- FW_CStyle style(FW_IntToFixed(3));
- FW_CLineShape lineShape(FW_kZeroPoint, newPoint);
- lineShape.SetInk(FW_kInvertInk);
- lineShape.SetStyle(style);
- lineShape.Render(gc);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawMinuteHand
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::DrawMinuteHand(Environment* ev,
- FW_CGraphicContext& gc,
- FW_Fixed minute)
- {
- 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 radians = ::DegreesToRadians(FW_MultipliedByInt(minute, 6));
-
- FW_CPoint newPoint = ::CalcPoint(minuteRadius, radians);
-
- FW_CStyle style(FW_IntToFixed(2));
- FW_CLineShape lineShape(FW_kZeroPoint, newPoint);
- lineShape.SetInk(FW_kInvertInk);
- lineShape.SetStyle(style);
- lineShape.Render(gc);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawSecondHand
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::DrawSecondHand(Environment* ev,
- FW_CGraphicContext& gc,
- FW_Fixed second)
- {
- 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);
- lineShape.SetInk(FW_kInvertInk);
- lineShape.Render(gc);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::UpdateAnalogClock
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::UpdateAnalogClock(Environment* ev,
- FW_CGraphicContext& gc,
- const FW_CTime& time)
- {
- // ----- Since we're called every second go ahead and update the second hand
- this->DrawSecondHand(ev, gc, FW_IntToFixed(fLastTime.GetSecond()));
- this->DrawSecondHand(ev, gc, FW_IntToFixed(time.GetSecond()));
-
- if (fLastTime.GetMinute() != time.GetMinute())
- {
- this->DrawMinuteHand(ev, gc, FW_IntToFixed(fLastTime.GetMinute()));
- this->DrawMinuteHand(ev, gc, FW_IntToFixed(time.GetMinute()));
-
- this->DrawHourHand(ev, gc, FW_IntToFixed(fLastTime.GetHour()), FW_IntToFixed(fLastTime.GetMinute()));
- this->DrawHourHand(ev, gc, FW_IntToFixed(time.GetHour()), FW_IntToFixed(time.GetMinute()));
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::UpdateDigitalClock
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::UpdateDigitalClock(Environment* ev,
- FW_CGraphicContext& gc,
- const FW_CTime& time)
- {
- FW_CString255 timeString;
- time.GetTimeString(timeString, TRUE);
-
- FW_CAcquiredODShape aqUsedShape(this->AcquireUsedShape(ev, NULL));
- FW_CRect usedShapeRect = FW_GetShapeBoundingBox(ev, aqUsedShape);
-
- FW_CRectShape rectShape(usedShapeRect, FW_kFill);
- rectShape.SetInk(FW_kWhiteEraseInk);
- rectShape.Render(gc);
-
- rectShape.SetRenderVerb(FW_kFrame);
- rectShape.Render(gc);
-
- FW_CTextBoxShape::RenderTextBox(gc, timeString, usedShapeRect, fDigitalFont, FW_kTextBoxJustifyHCenter);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::CreateSubViews
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::CreateSubViews(Environment* ev)
- {
- // ----- Create a GrowBox only in root frame
- if (this->IsRoot(ev))
- {
- FW_CRect frameRect = GetBounds(ev);
- FW_CPoint sbSize = FW_CScrollBar::GetDefaultScrollBarSize();
- frameRect.right -= sbSize.x;
- frameRect.bottom -= sbSize.y;
-
- FW_CGrowBox* growBox = new FW_CGrowBox(ev, this, 0, frameRect.BotRight());
- }
-
- }
-