home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Pascal / Applications / Flight Stability / Flight Stability Source / CBitmapWindow.p next >
Encoding:
Text File  |  1995-07-05  |  8.7 KB  |  334 lines  |  [TEXT/PJMM]

  1. (******************************************************************************}
  2. {}
  3. {        CBitmapWindow.p }
  4. {}
  5. {        SUPERCLASS = CWindow }
  6. {}
  7. {        Window class that draws via an offscreen bitmap. }
  8. {}
  9. {        Original author:  David Dunham. }
  10. {        For C++ . }
  11. {        Copyright ©1992 Pensée Corporation. }
  12. {        Pensée Corporation }
  13. {        532 N 71st St }
  14. {        Seattle, WA 98103-5127 }
  15. {}
  16. {        Pascal Translation: Patrick Hew. }
  17. {        For TCL 1.1.2 .}
  18. {     Copyright © 1995 Patrick Hew. }
  19. {        email: phew@ucc.gu.uwa.edu.au }
  20. {}
  21. {  CHANGE HISTORY }
  22. {}
  23. {        17 Apr 92        DRD    Tried offscreen drawing but took it out because CPane uses macPort. }
  24. {        18 Apr 92        DRD    A different approach to offscreen, replacing portBits. }
  25. {        24 Apr 92        DRD    Added (long) cast so we allocate offscreen screen-sized, not hardcoded. }
  26. {        03 May 92    DRD    Made into a stand-alone class, with a bitmap per window. }
  27. {        30 Aug 92        GHD    Moved Prepare() before MakeOffscreen in Update method. }
  28. {        30 Aug 92        GHD    Added Zoom method. }
  29. {}
  30. {        02 Jul 95        PH        First Pascal translation. }
  31. {                                                            Changed direct allocation of a pointer to allocating and locking a handle. }
  32. {}
  33. (******************************************************************************}
  34.  
  35.  
  36. unit CBitmapWindow;
  37.  
  38. interface
  39.  
  40.     uses
  41.         TCL;
  42.  
  43.     type
  44.         CBitmapWindow = object(CWindow)
  45.  
  46.                 {** Instance data **}
  47.  
  48.                 offscreen: BitMap;
  49.                 screenData: QDHandle;
  50.  
  51.                 {** Construction and destruction **}
  52.  
  53.                 procedure IWindowX;
  54.                 override;
  55.  
  56.                 procedure Free;
  57.                 override;
  58.  
  59.                 procedure MakeMacWindow (WINDid: Integer);
  60.                 override;
  61.  
  62.                 {** Size and location **}
  63.  
  64.                 procedure ChangeSize (width, height: Integer);
  65.                 override;
  66.  
  67.                 procedure Zoom (direction: integer);
  68.                 override;
  69.  
  70.                 {** Drawing **}
  71.  
  72.                 procedure MakeOffscreen;
  73.  
  74.                 procedure Update;
  75.                 override;
  76.  
  77.             end;
  78.  
  79.  
  80. implementation
  81.  
  82.     uses
  83.         CPane; { Pane_Draw }
  84.  
  85.  
  86. (******************************************************************************}
  87. {}
  88. {        IWindowX    (OVERRIDE) }
  89. {}
  90. {        Perform initialization commond to IWindow and INewWindow}
  91. {}
  92. {        We override here, rather than use the conventional IBitmapWindow, so that we can }
  93. {        use CBitmapWindow as a drop-in replacement for CWindow. No code has to be changed, }
  94. {        except the ancestry. This makes life much simpler when using AppMaker. }
  95. {}
  96. {******************************************************************************)
  97.  
  98.     procedure CBitmapWindow.IWindowX;
  99.  
  100.     begin { IWindowX }
  101.         inherited IWindowX;
  102.  
  103.         { We don't have a buffer yet. }
  104.         offscreen.baseAddr := nil;
  105.         screenData := nil;
  106.     end; { IWindowX }
  107.  
  108.  
  109. (******************************************************************************}
  110. {}
  111. {        Free (OVERRIDE) }
  112. {}
  113. {        Get rid of a window and all its panes. }
  114. {}
  115. (******************************************************************************}
  116.  
  117.     procedure CBitmapWindow.Free;
  118.  
  119.         var
  120.             theQDHandle: QDHandle;
  121.  
  122.     begin { Free }
  123.         { Free the memory we may have allocated. }
  124.         { Remember - Never pass an instance variable by reference. }
  125.         theQDHandle := screenData;
  126.         screenData := nil;
  127.         ForgetHandle(theQDHandle);
  128.  
  129.         inherited Free;
  130.     end; { Free }
  131.  
  132.  
  133. (******************************************************************************}
  134. {        MakeMacWindow (OVERRIDE) }
  135. {}
  136. {        Create a new Toolbox window record using the specified WIND }
  137. {        resource ID. This method creates a non-color window. }
  138. {}
  139. { ******************************************************************************)
  140.  
  141.     procedure CBitmapWindow.MakeMacWindow (WINDid: Integer);
  142.  
  143.         var
  144.             savedAlloc: Boolean;
  145.             behind: WindowPtr;
  146.  
  147.     begin { MakeMacWindow }
  148.         savedAlloc := SetAllocation(kAllocCanFail);
  149.  
  150.         if floating then begin
  151.             behind := WindowPtr(-1);
  152.         end { if }
  153.         else begin
  154.             behind := nil;
  155.         end; { else }
  156.  
  157.         macPort := GetNewWindow(WINDid, nil, behind);
  158.  
  159.         savedAlloc := SetAllocation(savedAlloc);
  160.  
  161.         FailNIL(macPort);
  162.     end; { MakeMacWindow }
  163.  
  164.  
  165. (******************************************************************************}
  166. {}
  167. {        ChangeSize (OVERRIDE) }
  168. {}
  169. {        Change the size of a window by specifying the width and height }
  170. {        in pixels. Window cannot be made larger than the maximum size }
  171. {        specified by its sizeRect instance variable. }
  172. {}
  173. { ******************************************************************************)
  174.  
  175.     procedure CBitmapWindow.ChangeSize (width, height: Integer);
  176.  
  177.         var
  178.             theQDHandle: QDHandle;
  179.  
  180.     begin { ChangeSize }
  181.         { Our offscreen bitmap is no longer the right size. }
  182.         { Remember - Never pass an instance variable by reference. }
  183.         theQDHandle := screenData;
  184.         screenData := nil;
  185.         ForgetHandle(theQDHandle);
  186.  
  187.         inherited ChangeSize(width, height);
  188.     end; { ChangeSize }
  189.  
  190.  
  191. (******************************************************************************}
  192. {}
  193. {        Zoom (OVERRIDE) }
  194. {}
  195. {        Zoom a window out to a standard size or in to its original size. }
  196. {}
  197. {******************************************************************************)
  198.  
  199.     procedure CBitmapWindow.Zoom (direction: integer);
  200.  
  201.         var
  202.             theQDHandle: QDHandle;
  203.  
  204.     begin { Zoom }
  205.         { Our offscreen bitmap is no longer the right size. }
  206.         { Remember - Never pass an instance variable by reference. }
  207.         theQDHandle := screenData;
  208.         screenData := nil;
  209.         ForgetHandle(theQDHandle);
  210.  
  211.         inherited Zoom(direction);
  212.     end; { Zoom }
  213.  
  214.  
  215. (******************************************************************************}
  216. {}
  217. {        MakeOffscreen }
  218. {}
  219. {        Initialize the offscreen bitmap. }
  220. {}
  221. {        For further discussion, refer to THINK Reference Ver2.00, "Creating Offscreen Bitmaps". }
  222. { ******************************************************************************)
  223.  
  224.     procedure CBitmapWindow.MakeOffscreen;
  225.  
  226.     begin {     MakeOffscreen }
  227.         { We don't want to call this twice. }
  228.         ASSERT(screenData = nil);
  229.  
  230.         { We make an offscreen BitMap as large as the window. }
  231.         offscreen.bounds := macPort^.portRect;
  232.  
  233.         { rowBytes is size of row, rounded up to an even number of bytes. }
  234.         offscreen.rowBytes := BSL(BSR((offscreen.bounds.right - offscreen.bounds.left + 15), 4), 1);
  235.  
  236.         { To minimize clogging of the heap, we allocate the offscreen memory here }
  237.         { as a handle. When we draw, we will lock the handle and set offscreen.baseAddr }
  238.         { to point to the block which is being handled. }
  239.         screenData := QDHandle(NewHandleCanFail(longint(offscreen.rowBytes * (offscreen.bounds.bottom - offscreen.bounds.top))));
  240.  
  241.         FailNIL(screenData);
  242.     end; {     MakeOffscreen }
  243.  
  244.  
  245. (******************************************************************************}
  246. {        Update}
  247. {}
  248. {        Update the contents of a window using an offscreen BitMap. (Because we’re }
  249. {        using a BitMap, the window cannot be a color GrafPort). Since Panes refer }
  250. {        to macPort, and expect it to be a WindowPeek, we can’t simply replace the port, }
  251. {        so we replace its portBits. }
  252. {}
  253. {        Drawing seems substantially slower, but it’s without flicker. }
  254. {}
  255. {******************************************************************************)
  256.  
  257.     procedure CBitmapWindow.Update;
  258.  
  259.         var
  260.             savePort: GrafPtr;                { The current port. }
  261.             updateRect: Rect;                    { Bounding box of the update region. }
  262.             savePortBits: BitMap;        { Window's original portBits. }
  263.  
  264.     begin { Update }
  265.         { Save the original port. }
  266.         GetPort(savePort);
  267.  
  268.         { Set up the Window's port. }
  269.         Prepare;
  270.  
  271.         { If we don't have an offscreen bitmap built yet, make it. }
  272.         if screenData = nil then begin
  273.             MakeOffscreen;
  274.         end; { if }
  275.         ASSERT(screenData <> nil);
  276.  
  277.         { Lock the block of screen data, and set the offscreen port }
  278.         { to point to it. }
  279.         HLockHi(screenData);
  280.         offscreen.baseAddr := screenData^;
  281.  
  282.         { Save the previous bitmap. }
  283.         savePortBits := thePort^.portBits;
  284.  
  285.         { Draw offscreen. }
  286.         { Make sure that the window is at corner. }
  287.         SetPortBits(offscreen);
  288.         MovePortTo(0, 0);
  289.  
  290.         { Get the bounding box of the update region, so we can draw only the panes }
  291.         { that intersect it. It's still in screen coordinates, so we have to offset it. }
  292.         updateRect := WindowPeek(macPort)^.updateRgn^^.rgnBBox;
  293.         OffsetRect(updateRect, savePortBits.bounds.left, savePortBits.bounds.top);
  294.  
  295.         { Draw all subviews. }
  296.         if (itsSubviews <> nil) then begin
  297.             { Clip to the update region. }
  298.             ClipRect(updateRect);
  299.  
  300.             { Erase the update region. }
  301.             EraseRect(updateRect);
  302.  
  303.             itsSubviews.DoForEach1(Pane_Draw, @updateRect);
  304.         end; { if }
  305.  
  306.         { Restore the previous bitmap. }
  307.         SetPortBits(savePortBits);
  308.         MovePortTo(-savePortBits.bounds.left, -savePortBits.bounds.top);
  309.  
  310.         { Start the update process. }
  311.         BeginUpdate(macPort);
  312.  
  313.         { Clip to the entire window. }
  314.         SetOrigin(0, 0);
  315.         ClipRect(thePort^.portRect);
  316.  
  317.         { Copy from offscreen to the update region. }
  318.         CopyBits(offscreen, savePortBits, updateRect, updateRect, srcCopy, nil);
  319.  
  320.         { End the update process. }
  321.         EndUpdate(macPort);
  322.  
  323.         { Restore the original port. }
  324.         SetPort(savePort);
  325.  
  326.         ForceNextPrepare;
  327.  
  328.         { Unlock the block of screen data, and reset the offscreen port. }
  329.         offscreen.baseAddr := nil;
  330.         HUnlock(screenData);
  331.     end; { Update }
  332.  
  333.  
  334. end. { CBitmapWindow }