home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / Bitmap / Sources / Part.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  16.4 KB  |  535 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                Part.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Author:                Henri Lamiraux
  7. //
  8. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9. //
  10. //========================================================================================
  11.  
  12. #include "Bitmap.hpp"
  13.  
  14. #ifndef PART_H
  15. #include "Part.h"
  16. #endif
  17.  
  18. #ifndef BINDING_K
  19. #include "Binding.k"
  20. #endif
  21.  
  22. #ifndef FRAME_H
  23. #include "Frame.h"
  24. #endif
  25.  
  26. #ifndef SELECT_H
  27. #include "Select.h"
  28. #endif
  29.  
  30. #ifndef CONTENT_H
  31. #include "Content.h"
  32. #endif
  33.  
  34. #ifndef DEFINES_K
  35. #include "Defines.k"
  36. #endif
  37.  
  38. // ----- Part Layer -----
  39.  
  40. #ifndef FWUTIL_H
  41. #include "FWUtil.h"
  42. #endif
  43.  
  44. #ifndef FWPRTITE_H
  45. #include "FWPrtIte.h"
  46. #endif
  47.  
  48. #ifndef FWITERS_H
  49. #include "FWIters.h"
  50. #endif
  51.  
  52. #ifndef FWABOUT_H
  53. #include "FWAbout.h"
  54. #endif
  55.  
  56. #ifndef FWPRESEN_H
  57. #include "FWPresen.h"
  58. #endif
  59.  
  60. // ----- OS Layer -----
  61.  
  62. #ifndef FWSUSINK_H
  63. #include "FWSUSink.h"
  64. #endif
  65.  
  66. #ifndef FWPICTUR_H
  67. #include "FWPictur.h"
  68. #endif
  69.  
  70. #ifndef FWEVENT_H
  71. #include "FWEvent.h"
  72. #endif
  73.  
  74. #ifndef FWBARRAY_H
  75. #include "FWBArray.h"
  76. #endif
  77.  
  78. #ifndef FWFILEAC_H
  79. #include "FWFileAc.h"
  80. #endif
  81.  
  82. #ifndef SLMixOS_H
  83. #include "SLMixOS.h"
  84. #endif
  85.  
  86. // ----- Foundation Layer -----
  87.  
  88. #ifndef FWSTREAM_H
  89. #include "FWStream.h"
  90. #endif
  91.  
  92. #ifndef FWMEMORY_H
  93. #include "FWMemory.h"
  94. #endif
  95.  
  96. #ifndef FWSUSINK_H
  97. #include "FWSUSink.h"
  98. #endif
  99.  
  100. // ----- OpenDoc Includes -----
  101.  
  102. #ifndef SOM_Module_OpenDoc_StdProps_defined
  103. #include <StdProps.xh>
  104. #endif
  105.  
  106. #ifndef SOM_ODTranslation_xh
  107. #include <Translt.xh>
  108. #endif
  109.  
  110. #ifndef SOM_ODSession_xh
  111. #include <ODSessn.xh>
  112. #endif
  113.  
  114. // ----- Macintosh Includes -----
  115.  
  116. #if defined(FW_BUILD_MAC) && !defined(__DRAG__)
  117. #include <Drag.h>
  118. #endif
  119.  
  120. // ----- Cyberdog Support -----
  121.  
  122. #if FW_SUPPORTS_CYBERDOG
  123. #include <Cyberdog.h>
  124. #include <CyberItem.xh>
  125. #include <CyberSession.xh>
  126. #include <CyberStream.xh>
  127. #include <ParameterSet.xh>
  128.  
  129. #ifndef FWCYPART_H
  130. #include "FWCyPart.h"
  131. #endif
  132.  
  133. #ifndef FWCYSTRM_H
  134. #include "FWCyStrm.h"
  135. #endif
  136.  
  137. #include "FWSaveAs.h"
  138. #include "odfjpeg.h"
  139. #endif
  140.  
  141. //========================================================================================
  142. //    Runtime Information
  143. //========================================================================================
  144.  
  145. #ifdef FW_BUILD_MAC
  146. #pragma segment odfbitmap
  147. #endif
  148.  
  149. //========================================================================================
  150. //    class CBitmapPart
  151. //========================================================================================
  152.  
  153. FW_DEFINE_AUTO(CBitmapPart)
  154.  
  155. //----------------------------------------------------------------------------------------
  156. //    CBitmapPart::CBitmapPart
  157. //----------------------------------------------------------------------------------------
  158. //    CBitmapPart constructor
  159.  
  160. CBitmapPart::CBitmapPart(ODPart* odPart) :
  161.     FW_CPart(odPart, FW_gInstance, kPartInfoID),
  162. #if FW_SUPPORTS_CYBERDOG
  163.     fHelper (kODNULL),
  164.     fReloadContinuously (false),
  165. #endif
  166.     fBitmapContent(NULL),
  167.     fBitmapPresentation(NULL)
  168. {
  169.     FW_END_CONSTRUCTOR
  170. }
  171.  
  172. //----------------------------------------------------------------------------------------
  173. //    CBitmapPart::~CBitmapPart
  174. //----------------------------------------------------------------------------------------
  175. // CBitmapPart destructor
  176.  
  177. CBitmapPart::~CBitmapPart()
  178. {
  179.     FW_START_DESTRUCTOR
  180. }
  181.  
  182. //----------------------------------------------------------------------------------------
  183. //    CBitmapPart::Initialize
  184. //----------------------------------------------------------------------------------------
  185. //    ODF Method
  186.  
  187. void CBitmapPart::Initialize(Environment* ev, ODStorageUnit* storageUnit, FW_Boolean fromStorage)
  188. {
  189.     // ----- Call first inherited -----
  190.     FW_CPart::Initialize(ev, storageUnit, fromStorage);
  191.     
  192. #if FW_SUPPORTS_CYBERDOG
  193. /*
  194.     ----- Cyberdog: Implementing your Cyberdog Part Extension -----
  195.     
  196.     The first thing you want to do is to add support for the CyberPartExtension 
  197.     (for details on this, see chapter 4 of the Cyberdog Programmer’s Guide, 
  198.     "Creating a Cyberdog Display Part", under the heading "Implementing your 
  199.     Cyberdog Part Extension").
  200.     
  201.     ODF encapsulates all the CyberPartExtension support in the 
  202.     FW_CCyberdogHelper class. You’ll want to create an instance of 
  203.     FW_CCyberdogHelper along with your part. Create the instance in your part’s 
  204.     Initialize method, like so:
  205. */
  206.     fHelper = ::FW_SupportCyberdogIfPresent (ev, this, FW_kUseCyberMenus, cCyberdogCommands, FW_kUseNavigator);
  207. /*
  208.     FW_SupportCyberdogIfPresent returns null if Cyberdog is not installed.
  209.     It is NOT necessary to delete the helper because it is an eventhandler
  210.     and will be deleted by FW_CPart automatically.
  211.  
  212.     You may choose whether you want the Cyberdog menus displayed in your part or 
  213.     not (FW_kUseCyberMenus); you may also choose whether you want your part to 
  214.     be displayed in the Cyberdog navigator/browser (FW_kUseNavigator).
  215.     
  216.     If you want the Cyberdog menus then you must reserve a range of command 
  217.     numbers for them as well. ODFBitmap defines cCyberdogCommands in Defines.k.
  218.     
  219.     ----- Creating a Stream for Downloading -----
  220.     
  221.     When a Cyberdog item is opened, Cyberdog calls your part extension's 
  222.     SetCyberItem method. ODF will then call the helper's DoSetCyberItem
  223.     method. You may register a function to be called automatically. Here 
  224.     "LoadCyberItem" will be called, and "this" will be passed to it.
  225.     Notice that for ODFBitmap, LoadCyberItem is a static member function, not
  226.     a global function, but it makes no difference.
  227. */
  228.     if (fHelper)
  229.         fHelper->SetLoadCyberItemThreadProcedure (LoadCyberItem, this);
  230. #endif
  231.     
  232.     // ----- Register our Presentations
  233.     fBitmapPresentation = RegisterPresentation(ev, 
  234.                                             "Apple:Presentation:ODFBitmap", 
  235.                                             TRUE, 
  236.                                             FW_NEW(CBitmapSelection, (ev, this, fBitmapContent)));
  237.  
  238.     // ----- Register our other kinds -----
  239.     RegisterKind(ev, kPICTOSType, kODPlatformDataType, FW_kDataInterchangeStorage, FW_kImportExportEnabled);
  240.     RegisterKind(ev, kPICTOSType, kODPlatformFileType, FW_kAllStorage, FW_kImport);
  241.     RegisterKind(ev, kJPEGOSType, kODPlatformDataType, FW_kDataInterchangeStorage, FW_kImport);
  242.     RegisterKind(ev, kJPEGOSType, kODPlatformFileType, FW_kAllStorage, FW_kImport);
  243.     RegisterKind(ev, kJFIFOSType, kODPlatformDataType, FW_kDataInterchangeStorage, FW_kImport);
  244.     RegisterKind(ev, kJFIFOSType, kODPlatformFileType, FW_kAllStorage, FW_kImport);
  245. }
  246.  
  247. //----------------------------------------------------------------------------------------
  248. //    CBitmapPart::NewDocumentWindow
  249. //----------------------------------------------------------------------------------------
  250.  
  251. FW_CWindow* CBitmapPart::NewDocumentWindow(Environment* ev)
  252. {    
  253.     FW_CRect bitmapRect;
  254.     fBitmapContent->GetBitmap(ev).GetBitmapBounds(bitmapRect);    // return in 72 dpi
  255. #ifdef FW_BUILD_MAC
  256.     // Leave some room for the grow box
  257.     bitmapRect.Inset(FW_IntToFixed(-16), FW_IntToFixed(-16));
  258. #endif
  259.     
  260.     FW_CRect screenBounds;
  261.     ::FW_GetMainScreenBounds(screenBounds);
  262.     screenBounds.Inset(FW_IntToFixed(3), FW_IntToFixed(3));
  263.     
  264.     return new FW_CWindow(ev,
  265.                         this,
  266.                          FW_CPart::fgViewAsFrameToken,
  267.                         fBitmapPresentation,
  268.                         bitmapRect.Size(),
  269.                         screenBounds.TopLeft(),
  270.                         FW_kDocumentWindow);
  271. }
  272.  
  273. //----------------------------------------------------------------------------------------
  274. //    CBitmapPart::NewPartContent
  275. //----------------------------------------------------------------------------------------
  276. //    ODF Method
  277.  
  278. FW_CContent* CBitmapPart::NewPartContent(Environment* ev)
  279. {
  280.     fBitmapContent = FW_NEW(CBitmapContent, (ev, this));
  281.     return fBitmapContent;
  282. }
  283.  
  284. #if FW_SUPPORTS_CYBERDOG
  285.  
  286.  
  287. //----------------------------------------------------------------------------------------
  288. //    CBitmapPart::DoAdjustMenus
  289. //    See "Cyberdog: Live Data" below in DoMenu.
  290. //----------------------------------------------------------------------------------------
  291.  
  292. FW_Handled CBitmapPart::DoAdjustMenus(Environment* ev, FW_CMenuBar* menuBar, FW_Boolean hasMenuFocus, FW_Boolean isRoot)
  293. {
  294. FW_UNUSED(isRoot);
  295.     if (hasMenuFocus && fHelper) {
  296.         menuBar->EnableCommand (ev, cReload, fHelper->GetCyberItem(ev) != kODNULL);
  297.         menuBar->EnableAndCheckCommand (ev, cReloadFast, TRUE, fReloadContinuously);    
  298.     }
  299.     
  300.     return FW_kNotHandled;
  301. }
  302.  
  303. #endif
  304.  
  305. //----------------------------------------------------------------------------------------
  306. //    CBitmapPart::DoAbout
  307. //----------------------------------------------------------------------------------------
  308.  
  309. FW_Handled CBitmapPart::DoAbout(Environment* ev)
  310. {
  311.     ::FW_About(ev, this, kAbout);
  312.     
  313.     return FW_kHandled;
  314. }
  315.  
  316. //----------------------------------------------------------------------------------------
  317. //    CBitmapPart::DoMenu
  318. //----------------------------------------------------------------------------------------
  319. // ODF method
  320.  
  321. #if FW_SUPPORTS_CYBERDOG
  322.  
  323. FW_Handled CBitmapPart::DoMenu(Environment* ev, const FW_CMenuEvent& theMenuEvent)
  324. {
  325.     FW_Handled result = FW_kHandled;
  326.     
  327.     ODCommandID id = theMenuEvent.GetCommandID(ev);
  328. /*
  329.     ----- Cyberdog: Live Data -----
  330.     
  331.     This is a cute feature which you may be able to put to real use.
  332.     The Cyberdog Navigator has a "reload" command but it actually loads a new
  333.     part (Cyberdog never calls you part to download data more than once). This 
  334.     Reload command will cause your part to open its CyberItem and download 
  335.     its data again (which may of course be updated data). A stock ticker
  336.     part could make use of this for example.
  337.     
  338.     Unfortunately Bitmap flashes but that could be solved by offscreen 
  339.     buffering. And "Reload Continuously" would be improved by a Sleep delay.
  340. */
  341.     if (id == cReload && fHelper) {
  342.         fHelper->GetExtension(ev)->SetCyberItem (ev, fHelper->GetCyberItem(ev), kODNULL);
  343.     }
  344.     else if (id == cReloadFast && fHelper) {
  345.         fReloadContinuously = !fReloadContinuously;
  346.     }
  347.     else if (id == kODCommandSaveACopy && fHelper) {
  348. /*
  349.     ----- Cyberdog: Embedding in the Navigator (SaveAs) -----
  350.     
  351.     You would think that OpenDoc would handle SaveAs. It does, but it can
  352.     only save another OD document. When we're doing browsing we frequently have
  353.     pictures, etc, which we want to save as normal MacOS documents. Until
  354.     OpenDoc supports multi-kind SaveAs, parts must do that themselves.
  355.     
  356.     Also, if we have a navigator part at the root, we might not want to save
  357.     it. Therefore there are two situations where you need to use this SaveAs
  358.     code: (1) Navigator is root part (2) You have multiple export kinds.
  359.  
  360.     In fact you **MUST** support SaveAs anyway if you want to be embeddable in 
  361.     the Navigator, because Cyberdog disables the OpenDoc Save mechanism.
  362.     
  363.     Basic question: Why would you implement your own Save As code instead of using 
  364.     OpenDocs? Because...
  365.     (1) you want to export files as standard MacOS documents (not OD documents).
  366.     (2) you don't want the navigator (browser) saved as the root part of the 
  367.     document.
  368.  
  369.     The new logic is to use the custom Save As code whenever we're in a 
  370.     "Cyberdog environment". That is...
  371.     (1) navigator is the root part.
  372.     (2) you are the root part but are in a Cyberdog draft.
  373.  
  374.     Note that being in a Cyberdog draft does not imply being in a "Cyberdog 
  375.     environment". For example, one could have ODFDraw, with a navigator embedded 
  376.     in it, and your part in the navigator. Your part would be in a Cyberdog 
  377.     draft but it would be important to use the default OD mechanism (since you 
  378.     want to save the whole document, not just your part).
  379.  
  380.     Note also that it's possible to be an embedded part in a part in the 
  381.     navigator. The logic doesn't handle this yet, but Cyberdog doesn't do 
  382.     embedded yet either, so it's not a problem which must be solved for R2.
  383. */
  384.         CyberSession* session = GetCyberSession(ev);
  385.         FW_Boolean inCyberDraft = session->IsInCyberDraft (ev, GetODPart(ev));
  386.         FW_CFrame* probableFrame = GetLastActiveFrame(ev);
  387.         FW_Boolean isRoot = probableFrame->IsRoot(ev);
  388.         FW_Boolean isInRootNavigator = false;
  389.         if (!isRoot) {
  390.             FW_CAcquiredODPart nav = fHelper->AcquireContainingNavigator (ev);
  391.             FW_Boolean isInNavigator = (nav != kODNULL);
  392.             if (isInNavigator)
  393.                 isInRootNavigator = session->IsContainedInRootNavigatorPart (ev, probableFrame->GetODFrame(ev));
  394.         }
  395.         FW_Boolean handle = (isInRootNavigator || (isRoot && inCyberDraft));
  396.         if (!handle)
  397.             return FW_kNotHandled;
  398.         // Get a default name
  399.         FW_PFileSpecification whichFile (ev, "");
  400.         short whichKind;
  401.         FW_CString defaultName;
  402.         if (fHelper && fHelper->GetCyberItem(ev)) {
  403.             Str255 itemName;
  404.             ScriptCode dummy;
  405.             fHelper->GetCyberItem(ev)->GetStringProperty (ev, kCDFileName, itemName, &dummy);
  406.             defaultName.ReplaceAll (itemName);
  407.         }
  408.         // Ask
  409.         Boolean doIt = ::FW_AskSaveAs (kSaveAs, defaultName, whichFile, whichKind);
  410.         if (doIt) {
  411.             // Can't do OpenDoc or CyberItem yet
  412.             if (whichKind == 1 || whichKind == 2) {
  413.                 FW_ASSERT (("Sorry, not yet implemented!", false));
  414.                 FW_Failure (FW_xUnknownError);
  415.             }
  416.             // Set up Picture file
  417. #ifdef FW_BUILD_MAC
  418.             whichFile->MacSetTypeAndCreator (ev, 'PICT', 'JVWR');
  419. #endif
  420. //            if (FW_FileSystem_IsValidFile (ev, whichFile))
  421. //                FW_FileSystem_DeleteFile (ev, whichFile);
  422.             FW_FileSystem_CreateFile (ev, whichFile, true);
  423.             FW_CAccessPermission permission (FW_kWrite);
  424.             FW_PFile file (ev, whichFile, permission, true); 
  425.             FW_PFileSink sink (ev, file);
  426.             FW_CWritableStream stream (sink);
  427.             // Write it out
  428. #ifdef FW_BUILD_MAC
  429.             // PICT format is wierd. 512 bytes of nothing?
  430.             char dummy [512];
  431.             memset (dummy, 0, 512);
  432.             sink->Write (ev, dummy, 512);
  433. #endif
  434.             FW_CPicture picture = fBitmapContent->GetBitmap(ev).MacGetAsPicture();
  435.             FW_PlatformPict platformPict = picture.GetPlatformPict();
  436.             unsigned long pictSize = FW_CMemoryManager::GetSystemHandleSize((FW_PlatformHandle)platformPict);
  437.             FW_CAcquireLockedSystemHandle lockedHandle((FW_PlatformHandle)platformPict);
  438.             stream.Write(lockedHandle.GetPointer(), pictSize);    
  439.         }
  440.     }
  441.     else
  442.         result = FW_kNotHandled;
  443.         
  444.     return result;
  445. }
  446.  
  447. #endif
  448.  
  449. //----------------------------------------------------------------------------------------
  450. // CBitmapPart::UpdatePresentation
  451. //----------------------------------------------------------------------------------------
  452.  
  453. void CBitmapPart::UpdatePresentation(Environment* ev)
  454. {
  455.     // ----- Force all display frames to be redrawn
  456.     fBitmapPresentation->Invalidate(ev);
  457.     
  458.     // ----- Force thumbnail to be recalculated -----
  459.     fBitmapPresentation->UpdateViewAs(ev);
  460. }
  461.  
  462. //----------------------------------------------------------------------------------------
  463. //    CBitmapPart::NewFrame
  464. //----------------------------------------------------------------------------------------
  465. // ODF Method
  466.  
  467. FW_CFrame* CBitmapPart::NewFrame(Environment* ev,
  468.                                  ODFrame* odFrame, 
  469.                                  FW_CPresentation* presentation,
  470.                                     FW_Boolean fromStorage)
  471. {
  472.     FW_UNUSED(fromStorage);
  473.     FW_ASSERT(presentation == fBitmapPresentation);
  474.  
  475.     return FW_NEW(CBitmapFrame, (ev, odFrame, presentation, this, fBitmapContent));
  476. }
  477.  
  478. //----------------------------------------------------------------------------------------
  479. //    CBitmapPart::AdjustFramesSize
  480. //----------------------------------------------------------------------------------------
  481. //    Bitmap Part Method
  482.  
  483. void CBitmapPart::AdjustFramesSize(Environment* ev)
  484. {
  485.     FW_CPartFrameIterator ite(ev, this);
  486.     for (CBitmapFrame* frame = (CBitmapFrame*)ite.First(ev); ite.IsNotComplete(ev); frame = (CBitmapFrame*)ite.Next(ev))
  487.     {
  488.         frame->AdjustFrameSize(ev);
  489.     }
  490. }
  491.  
  492. #if FW_SUPPORTS_CYBERDOG
  493.  
  494. //----------------------------------------------------------------------------------------
  495. // CBitmapPart::LoadCyberItem
  496. //----------------------------------------------------------------------------------------
  497.  
  498. void CBitmapPart::LoadCyberItem (Environment* ev, void* selfCPart)
  499. {
  500. /*
  501.     ----- Cyberdog: Creating a Stream for Downloading -----
  502.     
  503.     This static method will be called automatically when a Cyberdog item is 
  504.     opened. It has been registered via SetLoadCyberItemThreadProcedure, which
  505.     creates a new thread before calling this method. Since LoadCyberItem is
  506.     running in its own thread, it can wait for data to arrive without holding
  507.     up the user interface.
  508.     
  509. */
  510.     // Note this is a static method. "this" is passed in from Initialize
  511.     CBitmapPart* self = (CBitmapPart*) selfCPart;
  512.     
  513.     CyberItem* item = self->fHelper->GetCyberItem(ev);
  514.     
  515.     // Support continuous downloads
  516.     // We could do it by re-spawning our thread, but that causes problems
  517.     // with the smart pointer (can't create a new thread while the original
  518.     // one still exists). Therefore we'll just loop in the current thread.
  519.     do {
  520.     
  521.     CyberStream* cStream = item->CreateCyberStream (ev);
  522.     cStream->Open (ev);
  523.     FW_PCyberSink sink (ev, cStream);
  524.     
  525.     FW_CBitmap b = ODF_JPEG_Read (ev, sink);
  526.     self->fBitmapContent->SetBitmap (ev, b);
  527.     self->fBitmapPresentation->Invalidate(ev);
  528.     
  529.     }
  530.     while (self->fReloadContinuously);
  531. }
  532.  
  533. #endif // FW_SUPPORTS_CYBERDOG
  534.  
  535.