home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ctcoll95.zip
/
RAHMEN
/
PART_MAC.SEA
/
CPRedPart.cpp
next >
Wrap
Text File
|
1995-03-24
|
43KB
|
1,483 lines
/*
File: CPRedPart.cpp
Contains: CPRedPart OpenDoc part editor class implementation.
Built using PartMaker, then modified by JÜrn Loviscach,
c╒t Magazin fƒr Computertechnik
Written by: Tantek éelik, Eric Soldan, Jens Alfke, AND PartMaker
*/
#ifndef _ALTPOINT_
#include <AltPoint.h>
#endif
#ifndef _CPREDPART_
#include "CPRedPart.h"
#endif
#ifndef _PARTUTILS_
#include "PartUtils.h"
#endif
#ifndef _REDPARTDEF_
#include "RedPartDef.h"
#endif
#ifndef _USERSRCM_
#include <UseRsrcM.h>
#endif
#ifndef _INFOUTIL_
#include <InfoUtil.h>
#endif
#ifndef _ITEXT_
#include <IText.h>
#endif
#ifndef SOM_ODDraft_xh
#include <Draft.xh>
#endif
#ifndef SOM_ODArbitrator_xh
#include <Arbitrat.xh>
#endif
#ifndef SOM_ODCanvas_xh
#include <Canvas.xh>
#endif
#ifndef SOM_ODPart_xh
#include <Part.xh>
#endif
#ifndef SOM_ODFacet_xh
#include <Facet.xh>
#endif
#ifndef SOM_ODFrame_xh
#include <Frame.xh>
#endif
#ifndef SOM_ODFrameFacetIterator_xh
#include <FrFaItr.xh>
#endif
#ifndef SOM_ODFoci_xh
#include <Foci.xh>
#endif
#ifndef SOM_ODInfo_xh
#include <Info.xh>
#endif
#ifndef SOM_ODPstObj_
#include <PstObj.xh>
#endif
#ifndef SOM_ODShape_xh
#include <Shape.xh>
#endif
#ifndef SOM_ODStdProps_xh
#include <StdProps.xh>
#endif
#ifndef SOM_ODStdTypes_xh
#include <StdTypes.xh>
#endif
#ifndef _STDDEFS_
#include <StdDefs.h>
#endif
#ifndef _PLFMDEF_
#include <PlfmDef.h>
#endif
#ifndef SOM_ODCmdDefs_xh
#include <CmdDefs.xh>
#endif
#ifndef SOM_ODStorageU_xh
#include <StorageU.xh>
#endif
#ifndef SOM_ODTrnsform_xh
#include <Trnsform.xh>
#endif
#ifndef SOM_ODFocusSet_xh
#include <FocusSet.xh>
#endif
#ifndef SOM_ODFoci_xh
#include <Foci.xh>
#endif
#ifndef SOM_ODMenuBar_xh
#include <MenuBar.xh>
#endif
#ifndef SOM_ODWindow_xh
#include <Window.xh>
#endif
#ifndef SOM_ODWinStat_xh
#include <WinStat.xh>
#endif
#ifndef SOM_ODSession_xh
#include <ODSessn.xh>
#endif
#ifndef _PASCLSTR_
#include <PasclStr.h>
#endif
#ifndef _FOCUSLIB_
#include <FocusLib.h>
#endif
#ifndef __ERRORS__
#include <Errors.h>
#endif
#ifndef __RESOURCES__
#include <Resources.h>
#endif
#ifndef __DIALOGS__
#include <Dialogs.h>
#endif
#ifndef __TOOLUTILS__
#include <ToolUtils.h>
#endif
//====================================================================
// Miscellaneous
//====================================================================
#if qDebug
#define WeBeHere(StringPtr) DebugStr(StringPtr)
#else
#define WeBeHere(StringPtr)
#endif
#ifdef applec
#pragma segment RedPart
#endif
ODSession* gSession = kODNULL;
//====================================================================
// Constants
//====================================================================
const short kContentStringResID = 5000;
const short kContentStringID = 1;
const short kAboutTextID = 2;
const short kShowPartsBinID = 3;
const short kHidePartsBinID = 4;
//====================================================================
// CPRedPart
//====================================================================
//--------------------------------------------------------------------
// CPRedPart::CPRedPart
//--------------------------------------------------------------------
CPRedPart::CPRedPart()
{
WeBeHere("\pCPRedPart::CPRedPart");
fDirty = kODFalse;
fWindowID = 0;
fSession = kODNULL;
fMenuBar = kODNULL;
fPartsBinWin = 0;
fPartsBinOpen = kODFalse;
// Note that fFacetList is a static field, and therefore
// its constructor is automatically called before
// CPRedPart constructor.
}
//--------------------------------------------------------------------
// CPRedPart::~CPRedPart
//--------------------------------------------------------------------
CPRedPart::~CPRedPart()
{
WeBeHere("\pCPRedPart::~CPRedPart");
}
//--------------------------------------------------------------------
// CPRedPart::InitPart
//--------------------------------------------------------------------
void CPRedPart::InitPart(Environment* ev, ODStorageUnit* storageUnit, ODPart* partWrapper)
// Called by the draft object.
{
WeBeHere("\pCPRedPart::InitPart");
fPartWrapper = partWrapper; // Will very much need this later.
this->MyCommonInitPart(ev); // We say "this" everywhere just to be explicit.
storageUnit->AddProperty(ev, kODPropContents)->AddValue(ev, kRedPartKind);
// For your edification, AddProperty & AddValue
// implicitly focus. Check the API for more info.
{
CUsingLibraryResources fil;
//::GetIndString(fTextData, kContentStringResID, kContentStringID); //gestrichen, jl
} // Use CUsingLibraryResources to use your part's resource fork.
// Make it go out of scope when you are done.
// We are creating our part's initial content here.
// Initialize your other fields here.
fDirty = kODTrue;
this->fCount = 0L;//eingefƒgt, jl
}
//--------------------------------------------------------------------
// CPRedPart::InitPartFromStorage
//--------------------------------------------------------------------
void CPRedPart::InitPartFromStorage(Environment* ev, ODStorageUnit* storageUnit, ODPart* partWrapper)
// Called by the draft object.
{
WeBeHere("\pCPRedPart::InitPartFromStorage");
fPartWrapper = partWrapper; // Will very much need this later.
this->MyCommonInitPart(ev);
storageUnit->Focus(ev, kODPropContents, kODPosSame,
kRedPartKind, 0, kODPosSame);
//fTextData[0] = (unsigned char)storageUnit->GetSize(ev);
storageUnit->GetValue(ev, sizeof(long), &(this->fCount)); //geèndert, jl
}
//--------------------------------------------------------------------
// CPRedPart::MyCommonInitPart
//--------------------------------------------------------------------
void CPRedPart::MyCommonInitPart(Environment* ev)
{
WeBeHere("\pCPRedPart::MyCommonInitPart");
fSession = fPartWrapper->GetStorageUnit(ev)->GetSession(ev);
// As your part grows, add your initialization that is common
// between InitPart and InitPartFromStorage here.
// Note that GetStorageUnit can be used, since just prior to
// calling this method, InitPart calledInitPersistentObject or
// InitPartFromStorage called InitPersistentObjectFromStorage.
fSelectionFocus = fSession->Tokenize(ev, kODSelectionFocus);
fMenuFocus = fSession->Tokenize(ev, kODMenuFocus);
fKeyFocus = fSession->Tokenize(ev, kODKeyFocus);
fModalFocus = fSession->Tokenize(ev, kODModalFocus);
fFocusSet = new ODFocusSet();
fFocusSet->InitFocusSet(ev);
fFocusSet->Add(ev, fKeyFocus);
fFocusSet->Add(ev, fMenuFocus);
fFocusSet->Add(ev, fSelectionFocus);
fMenuBar = fSession->GetWindowState(ev)->CopyBaseMenuBar(ev);
{
CUsingLibraryResources fil;
fMenu = ::GetMenu(kMenuID);
if (fMenu)
::DetachResource((Handle)fMenu); // Must detach it!
}
if (!fMenu)
DebugStr("\pCPRedPart::MyCommonMyInitPart -- couldn't create menu.");
// Note that THROW, while valid under the temporary ASLM
// implementation of OpenDoc, won't be correct when OpenDoc
// is converted to SOM. Therefore we are using debug messages
// for these types of errors. When SOM is available, this issue
// will be addressed correctly.
fMenuBar->AddMenuLast(ev, kMenuID, fMenu, fPartWrapper);
}
//--------------------------------------------------------------------
// CPRedPart::Externalize
//--------------------------------------------------------------------
void CPRedPart::Externalize(Environment* ev)
{
WeBeHere("\pCPRedPart::Externalize");
if (fDirty != kODFalse)
{
ODStorageUnit* storageUnit = fPartWrapper->GetStorageUnit(ev);
// Get the reference to where we are writing to.
storageUnit->Focus(ev, kODPropContents, kODPosSame, kRedPartKind, 0, kODPosSame);
// First we focus on the property we want to write out.
storageUnit->SetValue(ev, sizeof(long), &(this->fCount)); //geèndert, jl
// Now we write out the property.
fDirty = kODFalse;
// Flag our part as no longer being dirty.
}
}
//-------------------------------------------------------------------------
// CPRedPart::MySetDirty
//-------------------------------------------------------------------------
void CPRedPart::MySetDirty(Environment* ev)
{
fDirty = kODTrue;
fPartWrapper->GetStorageUnit(ev)->GetDraft(ev)->SetChangedFromPrev(ev);
}
//-------------------------------------------------------------------------
// CPRedPart::Purge
//-------------------------------------------------------------------------
ODSize CPRedPart::Purge(Environment* ev, ODSize size)
{
ODUnused(size);
WeBeHere("\pCPRedPart::Purge");
// CPRedPart doesn't do anything here.
return 0;
}
//-------------------------------------------------------------------------
// CPRedPart::Release
//-------------------------------------------------------------------------
void CPRedPart::Release(Environment* ev)
{
WeBeHere("\pCPRedPart::Release");
// ÑÑ╩6/23/94
//
// If you are using RegisterIdle on the part, not on frames, then
// the RefCount is bumped up by one by OpenDoc. OpenDoc keeps a
// reference to all parts that register idle time. ALL OF THESE MUST
// BE RESOLVED BEFORE THE DESTRUCTOR IS CALLED. This is
// the place to do that.
// The logic below, assuming that CPRedPart has registered for idle
// time, is that if the RefCount is 1, then we are here to unregister
// the idle. When the part is being removed, OpenDoc must decrement
// the RefCount and call Release until the part gets messaged with
// a RefCount of 0. Once you return from here with a RefCount of 0,
// OpenDoc will call the destructor.
// This means that if you have registered for idle time, Release will
// be called TWICE when closing down your part. The first time the
// RefCount is 1. This is when you should unregister the idle time.
// When you are called with a RefCount of 0, that when it gets really
// serious. This is when you detach from the draft.
if (fPartWrapper->GetRefCount(ev) == 1) {
// Here is where you would unregister idle time for the part if
// have registered time. Note that if you unregister without
// registering, OpenDoc will crash. It's not just a simple
// look-up-and-if-there-remove kind of operation.
// Note that if you unregister idle here, OpenDoc will need to
// call Release (here) due to it. This means that when we call
// to unregister the idle, we are nesting calls to Release.
// Due to this, I return out of each case, just to make the
// flow of control of the call(s) to Release more straightforward.
// Note that if you are going to use idle registration, you will
// need to include "Disptch.h"
return;
}
}
//--------------------------------------------------------------------
// CPRedPart::Open
//--------------------------------------------------------------------
ODID CPRedPart::Open(Environment* ev, ODFrame* frame)
// Creates and opens a presentation of the part in a frame
// in a new window.
//
// This method adds this part as the root part of the window.
// It bases the presentation in the new frame on the presentation
// in the old frame, or on a default presentation if there
// is no old frame.
{
WeBeHere("\pCPRedPart::Open");
ODWindow* window = kODNULL;
if (frame)
window = fSession->GetWindowState(ev)->GetWindow(ev, fWindowID);
if (window == kODNULL)
{
window = this->MyMakeWindow(ev, frame);
fWindowID = window->GetID(ev);
window->Open(ev);
window->Show(ev);
}
window->Select(ev);
return window->GetID(ev);
}
//--------------------------------------------------------------------
// CPRedPart::ReleaseAll
//--------------------------------------------------------------------
void CPRedPart::ReleaseAll(Environment* ev)
{
WeBeHere("\pCPRedPart::ReleaseAll");
if (fMenuBar != kODNULL)
fMenuBar->Release(ev);
}
//--------------------------------------------------------------------
// CPRedPart::MyWantResizable
//--------------------------------------------------------------------
ODBoolean CPRedPart::MyWantResizable()
{
return kODFalse;
// used in MyMakeWindow() to toggle some parameters
}
//--------------------------------------------------------------------
// CPRedPart::MyMakeWindow
//--------------------------------------------------------------------
ODWindow* CPRedPart::MyMakeWindow(Environment* ev, ODFrame* sourceFrame)
{
WeBeHere("\pCPRedPart::MyMakeWindow");
Rect windRect;
ODPlatformWindow platformWindow = kODNULL;
ODWindow* window = kODNULL;
if (sourceFrame)
{
SetRect(&windRect, 100, 100, 300, 300);
}
else
{
const ODSShort kOnePageWidth = 600;
::SetRect(&windRect, 4, GetMBarHeight() + 24,
ODQDGlobals.screenBits.bounds.right - 64,
ODQDGlobals.screenBits.bounds.bottom - 4);
if (windRect.right - windRect.left > kOnePageWidth)
windRect.right = windRect.left + kOnePageWidth;
}
Str255 windowTitleStr;
ODName* partName = ODGetPOName(fPartWrapper, kODNULL);
IntlToPStr(partName, (StringPtr)&windowTitleStr);
DisposeIText(partName);
platformWindow = ::NewCWindow
(
kODNULL,
&windRect,
windowTitleStr,
false,
this->MyWantResizable() ? zoomDocProc : zoomNoGrow,
(WindowPtr)-1L,
true,
kODNULL
);
window = fSession->GetWindowState(ev)->RegisterWindow
(
ev,
platformWindow, // newWindow
kODNULL, // frameType
(sourceFrame == kODNULL), // isRootWindow
this->MyWantResizable(), // isResizable
kODFalse, // isFloating
kODTrue, // shouldSave
fPartWrapper, // rootPart
fSession->Tokenize(ev, kODViewAsFrame), // viewType
kODNullTypeToken, // presentation
sourceFrame // sourceFrame
);
return window;
}
//--------------------------------------------------------------------
// CPRedPart::Draw
//--------------------------------------------------------------------
void CPRedPart::Draw(Environment* ev, ODFacet* facet, ODShape* invalidShape)
// Draws the part in the facet, updating the portion of the
// facet in the invalidShape.
//
// Called by the facet object.
//
// The part should draw itself on the facet's canvas. The part
// must examine its canvas' isDynamic flag to determine if it
// will be drawing on the screen or to a printer, and then draw
// itself appropriately.
//
// Draw the part in the given facet. Only the portion in the
// invalidShape needs to be drawn.
//
// There are several steps a part needs to take to perform the
// imaging.
// 1) The part should look at the given facet and its frame.
// Both the frame and the facet may have some partInfo that
// the part has placed there, which the part can use to
// decide how it will display itself. The frame also has
// viewType and presentation fields, which indicate what kind
// of view of the part should display.
// 2) The part should examine its canvas to see how it should
// be imaged. The canvas can be obtained from the facet via
// ODFacet::GetCanvas(). If the canvas╒ isDynamic flag is
// kODTrue, the part is imaging onto a dynamic device like
// a CRT; otherwise, it is imaging to a static device like
// a printer. The part will probably display its content
// differently for static and dynamic views. For instance,
// it should not display scroll bars on a static canvas.
// 3) The part must make sure the platform graphics system is
// prepared to draw into the correct context for the facet.
// On the Macintosh using QuickDraw, it is necessary to call
// SetPort() for the appropriate canvas, and set up other
// attributes of the drawing environment. A FocusLib library
// is supplied to help focus drawing commands to a facet.
// Make sure to clip to the facet╒s clipShape (FocusLib
// does this for you).
// 4) Draw the part╒s contents.
// 5) Restore the old graphics environment.
//
// Part editors may sometimes need to display their parts
// asynchronously, that is, not in response to a ::Draw() call.
// This process is very similar to the basic drawing recipe,
// with minor modifications.
// 1) Determine which of the part╒s frames should be drawn. A part
// may have multiple display frames, and more than one may need
// updating. Parts store their display frames in whatever way
// they want, so we can╒t tell you how to find them here.
// 2) For each frame being displayed, all facets must be drawn.
// ODFrame::CreateFrameFacetIterator() returns an iterator
// which will list all the facets of a frame. Draw the part╒s
// contents in each of these facets, using the recipe above.
// 3) After drawing in a facet, call ODFacet::DrawnIn() on it to
// tell it you╒ve drawn in it asynchronously. If the facet is
// on an offscreen canvas, this lets it get copied into the window.
{
WeBeHere("\pCPRedPart::Draw");
ODUnused(invalidShape);
CFocus foc(ev, facet);
ODFrame* frame = facet->GetFrame(ev);
ODShape* usedShape = frame->GetUsedShape(ev, kODNULL);
RgnHandle rgn = usedShape->GetQDRegion(ev);
usedShape->Release(ev);
Rect rct = (*rgn)->rgnBBox;
RgnHandle oldClip = nil;
RgnHandle newClip;
::ForeColor(redColor); //ab hier geèndert, jl
::PaintRect(&rct);
::PenNormal();
::ForeColor(blackColor);
Str255 text;
::NumToString(this->fCount, text);
short x = (rct.right - rct.left - ::StringWidth(text)) / 2;
short y = (rct.bottom - rct.top - 12) / 2;
::MoveTo(x, y);
::DrawString(text);
if (oldClip) {
::SetClip(oldClip);
::DisposeRgn(oldClip);
}
}
//====================================================================
// PartsBin
//====================================================================
void CPRedPart::MyShowPartsBin(Environment* ev, ODFrame* frame)
{
WeBeHere("\pCPRedPart::MyShowPartsBin");
ODPart* partsbin;
ODStorageUnit* su = fPartWrapper->GetStorageUnit(ev);
ODStorageUnit* pbSU;
ODStorageUnitRef pbSURef;
ODStorageUnitID pbSUID;
if (su->Exists(ev, kODPropPartsBin,kODStrongStorageUnitRef,0))
{
su->Focus(ev, kODPropPartsBin,kODPosSame,kODStrongStorageUnitRef,1,kODPosFirstSib);
su->SetOffset(ev, 0);
su->GetValue(ev, sizeof(kODStrongStorageUnitRef), (ODValue)&pbSURef);
pbSUID = su->GetIDFromStorageUnitRef(ev, pbSURef);
partsbin = su->GetDraft(ev)->GetPart(ev, pbSUID);
}
else
{
su->AddProperty(ev, kODPropPartsBin)->AddValue(ev, kODStrongStorageUnitRef);
partsbin = su->GetDraft(ev)->CreatePart(ev, kODKindPartsBin, kODNULL);
if (partsbin != kODNULL)
{
pbSU = partsbin->GetStorageUnit(ev);
pbSURef = su->GetStrongStorageUnitRef(ev, pbSU->GetID(ev));
su->SetValue(ev, sizeof(kODStrongStorageUnitRef), (ODValue)&pbSURef);
}
else {
DebugStr("\pCannot Create Parts Bin");
}
}
fPartsBinWin = partsbin->Open(ev, frame);
partsbin->Release(ev);
fPartsBinOpen = kODTrue;
}
void CPRedPart::MyHidePartsBin(Environment* ev)
{
WeBeHere("\pCPRedPart::MyHidePartsBin");
if (fPartsBinOpen && fPartsBinWin)
{
ODWindow* pbWin = fSession->GetWindowState(ev)->GetWindow(ev, fPartsBinWin);
if (pbWin != kODNULL)
pbWin->Hide(ev);
else
DebugStr("\pCannot Hide Parts Bin");
fPartsBinOpen = kODFalse;
}
}
//-------------------------------------------------------------------------
// UI Events protocol
//-------------------------------------------------------------------------
ODBoolean CPRedPart::HandleEvent(Environment* ev, ODEventData* event,
ODFrame* frame, ODFacet* facet)
{
WeBeHere("\pCPRedPart::HandleEvent");
ODBoolean tWasHandled = kODFalse;
switch ( event->what ) {
case nullEvent:
if (::IsDialogEvent((EventRecord *)event))
{
short itemHit;
DialogPtr dialog;
tWasHandled = ::DialogSelect((EventRecord *)event, &dialog, &itemHit);
return tWasHandled;
}
tWasHandled = kODTrue;
break;
case mouseDown:
tWasHandled = this->MyHandleMouseDown(ev, event, frame, facet);
break;
case kODEvtMouseDownEmbedded:
case mouseUp:
case keyDown:
case autoKey:
case activateEvt:
tWasHandled = kODTrue;
break;
case kODEvtMenu:
tWasHandled = this->MyHandleMenuEvent(ev, frame, event );
break;
default:
break;
}
return tWasHandled;
// Below is some documentation for this method. If you don't care for
// being here, then just delete it.
//
// The frame and facet parameters of HandleEvent() may be
// kODNULL, depending on the kind of event.
//
// Parts must handle the following events, which correspond to
// standard Macintosh events:
//
// kODEvtNull
// kODEvtMouseDown
// kODEvtMouseUp
// kODEvtKeyDown
// kODEvtKeyUp
// kODEvtAutoKey
// kODEvtUpdate
// kODEvtActivate
// kODEvtOS
//
// Null Events --
// In order to receive null events (i.e. idle time), parts must call
// ODDispatcher::RegisterIdle(), specifying the part, a frame
// (optional) and idle frequency. The part will receive a null event
// for each frame registered. ODDispatcher::GetSleepTime() is called
// by the shell, and the value passed to WaitNextEvent. An appropriate
// sleep time is computed based on the idle frequencies of registered
// idle frames.
//
// Mouse Events --
// Unmodified mouse events are delivered to the facet under the mouse
// location using Part::HandleEvent().
//
// Shift-Click and Command-Click go to the frame with the selection
// focus. Mouse events in window title bars are converted to window
// events. (See below) Mouse down events in the menu bar are converted
// to menu events. (See below)
//
// Keyboard Events --
// Keyboard events go to the frame with the keyboard focus, with the
// exception of the Page Up, Page Down, Home and End keys, which will
// go to the frame with the scrolling focus, if there is one.
//
// Update Events --
// Update events are not passed to Part::HandleEvent(). Rather
// Part::Draw() will be called for each facet in the window.
//
// Activate Events --
// Activate events are also delivered to each facet, using
// Part::HandleEvent().
//
// Disk Events --
// Currently, disk events are not distributed to parts.
// But where do they go???
//
// OS Events --
// Suspend/Resume events are delivered to each facet in each
// window using Part::HandleEvent().
//
// Mouse Moved events are not passed to Part::HandleEvent().
// They are handled by the dispatcher, and translated into calls
// to Part::MouseEnter(), MouseWithin() and MouseLeave().
// See Cursor Tracking below.
//
// Menu Events --
// OpenDoc converts a mouse down in the menu bar, or its
// command-key equivalent, into a menu event of type kODEvtMenu.
//
// The message field of the event record contains the result
// returned by MenuSelect() or MenuKey(). i.e. the menu is in
// the high word, and the item in the low word. The part can
// obtain a command number using ODMenuBar::GetCommand().
//
// Window Events --
// Events in the title bar of a window (eg. clicking in the
// close box) are usually handled by the shell, but are first
// offered to the root part of the window. Parts which wish to
// intercept these events (perhaps to hide rather than close a
// window) must handle the following event: kODEvtWindow
// The message field of the event contains the part code, as
// returned by FindWindow().
//
// Events in Embedded Frames --
// Parts which support embedding may also receive the following events:
//
// kODEvtMouseDownEmbedded
// kODEvtMouseUpEmbedded
// kODEvtMouseDownBorder
// kODEvtMouseUpBorder
//
// If the user clicks in the active border, the containing
// facet/frame/part will receive a kODEvtMouseDownBorder event.
// The message field of the event record contains the embedded facet.
//
// Similarly, if the user clicks in an embedded frame with the
// ╥frozen╙ or ╥selected╙ property set, a kODEvtMouseDownEmbedded
// event is directed to the containing frame.
//
// If the user shift-clicks or command-clicks in a frame which is
// embedded in the frame with the selection focus, then the latter
// frame gets a kODEvtMouseDownEmbedded event.
//
// Cursor Tracking --
// OpenDoc tracks cursor movement (with the mouse button up), and
// calls MouseEnter() when the cursor first moves into a facet, and
// MouseLeave() when the cursor leaves the facet. A part can change
// the cursor on MouseEnter, and set it to the arrow on MouseLeave.
//
// This process is triggered by the shell calling
// ODDispatcher::GetMouseRegion() and passing the result to
// WaitNextEvent(). The region is only recomputed when necessary.
// If the cursor is motionless within a facet, the shell application
// goes to sleep because OpenDoc computes a mouse region containing
// just the cursor location. The part can make this region larger
// by calling ODDispatcher::SetMouseRegion(). In a future release,
// OpenDoc will also compute a suitably large sleep region if the
// cursor is not within any facet.
//
// Modal Focus --
// Some events are constrained by the modal focus. For example a
// mouse click outside the frame with the modal focus will be sent
// to the modal focus frame, but a click in an embedded frame
// within the modal focus frame will go to the embedded frame.
//
// Propagating Events --
// If a containing part sets the ╥DoesPropagateEvents╙ property of
// an embedded frame, the containing part will receive events not
// handled by the embedded frame. A part which does this will have
// to inspect the frame passed to HandleEvent() to determine if it
// is one of its display frames.
}
void CPRedPart::AdjustMenus(Environment* ev, ODFrame* frame)
{
Str63 aboutText, showPartsBin, hidePartsBin;
ODIText* odiText;
WeBeHere("\pCPRedPart::AdjustMenus");
ODUnused(frame);
fMenuBar->EnableCommand(ev, kODCommandViewAsWin, !frame->IsRoot(ev) );
fMenuBar->EnableCommand(ev, kODCommandGetPartInfo, kODTrue);
fMenuBar->EnableCommand(ev, kODCommandShowPartsBin, kODTrue);
{
CUsingLibraryResources fil;
::GetIndString(aboutText, kContentStringResID, kAboutTextID);
::GetIndString(showPartsBin, kContentStringResID, kShowPartsBinID);
::GetIndString(hidePartsBin, kContentStringResID, kHidePartsBinID);
}
odiText = CreateIText(kODRomanScript, kODEnglishLang, aboutText);
fMenuBar->SetItemString(ev, kODCommandAbout, odiText);
DisposeIText(odiText);
if (fPartsBinWin)
{
ODWindow* window = fSession->GetWindowState(ev)->GetWindow(ev, fPartsBinWin);
if (window)
fPartsBinOpen = window->IsShown(ev);
else
fPartsBinOpen = kODFalse;
}
if (fPartsBinOpen) {
odiText = CreateIText(kODRomanScript, kODEnglishLang, hidePartsBin);
fMenuBar->SetItemString(ev, kODCommandShowPartsBin, odiText);
DisposeIText(odiText);
}
else {
odiText = CreateIText(kODRomanScript, kODEnglishLang, showPartsBin);
fMenuBar->SetItemString(ev, kODCommandShowPartsBin, odiText);
DisposeIText(odiText);
}
}
//--------------------------------------------------------------------
// CPRedPart::MyHandleMenuEvent
//--------------------------------------------------------------------
ODBoolean CPRedPart::MyHandleMenuEvent(Environment* ev, ODFrame* frame, ODEventData* event)
{
WeBeHere("\pCPRedPart::MyHandleMenuEvent");
ODUnused(frame);
long menuResult = event->message;
short menu = HiWord(menuResult);
short item = LoWord(menuResult);
if (menu) { // If your custom menu(s)... ÑÑ 6/23/94
switch( fMenuBar->GetCommand(ev, menu, item) ) {
case kODCommandAbout:
{
CUsingLibraryResources fil;
if (fSession->GetArbitrator(ev)->RequestFocus(ev, fModalFocus, frame))
{
SetCursor(&ODQDGlobals.arrow);
gSession = fSession; // DialogFilter uses this!
ModalFilterUPP modalFilter = NewModalFilterProc(MyDialogFilter);
::Alert(kRedPartAboutBoxID, modalFilter);
DisposeRoutineDescriptor(modalFilter);
fSession->GetArbitrator(ev)->RelinquishFocus(ev, fModalFocus,frame);
}
else
::SysBeep(1);
}
break;
case kODCommandClear:
break;
case kODCommandShowPartsBin:
if (fPartsBinOpen)
this->MyHidePartsBin(ev);
else
this->MyShowPartsBin(ev, frame);
break;
case kODCommandViewAsWin:
this->Open(ev, frame);
break;
case kODCommandGetPartInfo:
ODFrameFacetIterator* facets = frame->CreateFacetIterator(ev);
fSession->GetInfo(ev)->ShowPartFrameInfo(ev, facets->First(ev));
break;
default:
return kODFalse;
}
}
return kODTrue;
}
//------------------------------------------------------------------------------
// CPRedPart::MyHandleMouseDown
//------------------------------------------------------------------------------
ODBoolean CPRedPart::MyHandleMouseDown(Environment* ev, ODEventData* event,
ODFrame* frame, ODFacet* facet)
{
WeBeHere("\pCPRedPart::MyHandleMouseDown");
ODBoolean handled = kODFalse;
if (facet == kODNULL) // Did we get a click outside a modal dialog? ╔
{
::SysBeep(1);
return kODTrue; // Return that click was handled.
}
// Activate the window if it is not active╔
if (!facet->GetWindow(ev)->IsActive(ev))
{
facet->GetWindow(ev)->Select(ev);
#ifdef FIRST_CLICK_WINDOW_BEHAVIOR
handled = kODTrue;
#else
return kODTrue;
#endif
// We argued way too much about which this should be. The answer is that
// some types of content need first click, and some absolutely don't. Even
// for 'TEXT', sometimes you want one, and sometimes you want the other.
// It depends on your content, usage model, etc.
//
// If you are unsure about which you want, the default for RedPart
// should be FIRST_CLICK_WINDOW_BEHAVIOR. This probably means fewer clicks
// for the user. If this doesn't work for your part, of course change it.
}
if (::IsDialogEvent((EventRecord *)event))
{
short itemHit;
DialogPtr dialog;
handled = ::DialogSelect((EventRecord *)event, &dialog, &itemHit);
ODWindow* window = fSession->GetWindowState(ev)->GetODWindow(ev, dialog);
return handled; // In preparation for more "if" cases to be added below.
}
// get the mouse in local coordinates
ODWindow* odwnd = frame->GetWindow(ev);
ODPoint odPoint;
GetWindowPoint(odwnd, ev, event->where, &odPoint);
// test for click in grow box, if appropriate
if (frame->IsRoot(ev))
{
WindowPtr wnd = (WindowPtr)odwnd->GetPlatformWindow(ev);
Rect r = wnd->portRect;
r.left = r.right - 15;
r.top = r.bottom - 15;
if (::PtInRect(odPoint.AsQDPoint(), &r)) {
::SetRect(&r, 200, 200, 20000, 20000);
long newWindowSize = GrowWindow(wnd, event->where, &r);
::SizeWindow(wnd, LoWord(newWindowSize), HiWord(newWindowSize), true);
odwnd->AdjustWindowShape(ev);
return kODTrue;
}
}
// Try to grab all of our foci╔
if ( fSession->GetArbitrator(ev)->RequestFocusSet(ev, fFocusSet,frame) )
{
this->FocusAcquired(ev, fSelectionFocus, frame);
this->FocusAcquired(ev, fMenuFocus, frame);
this->FocusAcquired(ev, fKeyFocus, frame);
} else {
return kODFalse; // We couldn't get focus.
// Of course, you shouldn't fail if you really don't need the *all*
// of the foci. For example, a vector drawing part that also has
// a text tool should probably go ahead and allow drawing while
// disabling the text tool.
}
// Handle clicks in used shape╔
odPoint = facet->GetWindowContentTransform(ev, kODNULL)->InvertPoint(ev, &odPoint);
ODShape* usedShape = this->MyGetUsedShape(ev, frame);
ODBoolean hit = usedShape->ContainsPoint(ev, &odPoint);
usedShape->Release(ev);
if (hit)
return this->MyUsedShapeHandleMouseDown(ev, event, frame, facet);
return handled;
}
//------------------------------------------------------------------------------
// CPRedPart::MyUsedShapeHandleMouseDown
//------------------------------------------------------------------------------
ODBoolean CPRedPart::MyUsedShapeHandleMouseDown(Environment* ev, ODEventData* event,
ODFrame* frame, ODFacet* facet)
{
WeBeHere("\pCPRedPart::MyUsedShapeHandleMouseDown");
// Get the window and platform window (i.e. WindowPtr)╔
ODWindow* odwnd = frame->GetWindow(ev);
ODPlatformWindow facetPort = odwnd->GetPlatformWindow(ev);
// Get the mouse in window-local and facet-local coordinates╔
ODPoint windowPoint;
GetWindowPoint(odwnd, ev, event->where, &windowPoint);
ODPoint facetPoint = facet->GetWindowContentTransform(ev, kODNULL)->
InvertPoint(ev, &windowPoint);
// Handle the click in whatever way is appropriate╔
{
CFocus foc(ev, facet);
//Rect rct; //das folgende auskommentiert, jl
//Point macPoint = facetPoint.AsQDPoint();
//::PenNormal();
//::PenMode(srcXor);
//::SetRect(&rct, macPoint.h - 3, macPoint.v - 3, macPoint.h + 3, macPoint.v + 3);
//::PaintOval(&rct);
//::PenNormal();
this->fCount++; //neu, jl
this->MySetDirty(ev); //neu
frame->Invalidate(ev,kODNULL,kODNULL); //neu
}
return kODTrue; // We handled the click.
}
//-------------------------------------------------------------------------
// Facet protocol
//-------------------------------------------------------------------------
void CPRedPart::FacetAdded(Environment* ev, ODFacet* facet)
{
WeBeHere("\pCPRedPart::FacetAdded");
// Add new facet to list of current facets.
fFacets.Add(facet);
ODFrame* frame = facet->GetFrame(ev);
frame->RequestFrameShape(ev, this->MyGetFrameShape(ev, frame), kODNULL);
// ÑÑ First, MyGetFrameShape is called to calculate the frame
// shape we want. However, we might not get it, due to the
// needs/constraints of the containing part. Therefore, after
// calculating what we want, we see if we can get it by calling
// RequestFrameShape.
// RequestFrameShape either returns us what we passed it, or
// returns something else because it thinks it knows best.
// Either way, we then proceed with the returned result.
// Note that this means that we have to be prepared to deal
// with a frame shape other than we desire.
this->MyAdjustFacets(ev, frame);
// Given a new negotiated frame shape, adjust our facets based
// on it. That's all there is to it.
if (frame->IsRoot(ev))
{
ODBoolean succeeded = kODFalse;
succeeded = fSession->GetArbitrator(ev)->RequestFocusSet(ev, fFocusSet,frame);
if (succeeded)
{
this->FocusAcquired(ev, fSelectionFocus, frame);
this->FocusAcquired(ev, fMenuFocus, frame);
this->FocusAcquired(ev, fKeyFocus, frame);
}
}
}
void CPRedPart::FacetRemoved(Environment* ev, ODFacet* facet)
{
WeBeHere("\pCPRedPart::FacetRemoved");
fFacets.Remove(facet);
// This just removes the reference from our facet list.
ODFrame* frame = facet->GetFrame(ev);
frame->RequestFrameShape(ev, this->MyGetFrameShape(ev, frame), kODNULL);
this->MyAdjustFacets(ev, frame);
// ÑÑ╩This is here in case losing a facet means that we need to recalculate
// the frame. This would occur if the part added some of its own facets,
// beyond the single facet that is automatically given to a frame. If
// you don't have your own additional facets, then this code renegotiates
// the frame shape for no reason, since the frame will be going away
// immediately afterwards (after the last/only facet is removed).
}
//--------------------------------------------------------------------
// CPRedPart::MyInvalAllFacets
//--------------------------------------------------------------------
void CPRedPart::MyInvalAllFacets(Environment* ev)
{
// This is just a CPRedPart utility method.
for (FacetLink *fl = fFacets.First(); fl->Facet(); fl=fl->Next())
fl->Facet()->Invalidate(ev, kODNULL, kODNULL);
}
//-------------------------------------------------------------------------
// Part Activation protocol
//-------------------------------------------------------------------------
ODBoolean CPRedPart::BeginRelinquishFocus(Environment* ev, ODTypeToken focus,
ODFrame* ownerFrame,
ODFrame* proposedFrame)
{
WeBeHere("\pCPRedPart::BeginRelinquishFocus");
ODUnused(ownerFrame);
if ((focus == fModalFocus) && (proposedFrame->GetPart(ev) != fPartWrapper)) {
return kODFalse;
// ÑÑ 6/23/94
// What IS ModalFocus, anyway? The whole purpose of this
// ModalFocus thing is to restrict frame changes. This is
// the part's chance to do this. But how much to restrict╔
//
// This is an interesting case. ModalFocus is kind of a weird
// concept in OpenDoc, as it goes against the principal of
// being able to click anywhere at any time. This implementation
// keeps the focus on the part. Note that the implementation
// of ModalFocus might be more restrictive than this. You may
// wish to restrict it to a single frame, instead of allowing
// the focus to move from frame to frame within a single part.
// If you wish to restrict it to a single frame, then the if
// should only check if it is a modal focus.
}
else {
return kODTrue;
// This is the super-script way of handling ModalFocus. You
// can NOT switch off the frame to another, no matter what.
}
}
void CPRedPart::CommitRelinquishFocus(Environment* ev, ODTypeToken focus, ODFrame* ownerFrame,
ODFrame* proposedFrame)
{
WeBeHere("\pCPRedPart::CommitRelinquishFocus");
ODUnused(proposedFrame);
this->FocusLost(ev, focus, ownerFrame);
// ÑÑ 6/23/94
// No choices to be made here. It's too late to say no. We are
// losing the focus if we are here. Getting called here means
// that BeginRelinquishFocus has already agreed that losing focus
// is okay. If you don't want this to be happening, then you need
// to do something in BeginRelinquishFocus.
//
// The way that some other samples are currently written I believe
// to be in error. The recipes say that when this is called, it
// has already been decided that, focus-wise, you lose. Therefore
// there should be no conditions on calling FocusLost.
}
void CPRedPart::AbortRelinquishFocus(Environment* ev, ODTypeToken focus, ODFrame* ownerFrame,
ODFrame* proposedFrame)
{
WeBeHere("\pCPRedPart::AbortRelinquishFocus");
ODUnused(focus);
ODUnused(ownerFrame);
ODUnused(proposedFrame);
// ÑÑ 6/23/94
// Being here means that BeginRelinquishFocus said no to one of the foci.
// You are being informed of this because you may have already taken action
// based on a previous focus. Note that if foci are managed as a set, if
// BeginRelinquishFocus says false to any of the foci, then no action is
// taken. If however the foci are tested one at a time, it is possible that
// the part has already taken action based on the first foci, and therefore
// needs to undo something once a foci says no thanks.
}
void CPRedPart::FocusAcquired(Environment* ev, ODTypeToken focus, ODFrame* ownerFrame)
{
WeBeHere("\pCPRedPart::FocusAcquired");
if (focus == fMenuFocus)
if (ownerFrame && fMenuBar)
{
fMenuBar->Display(ev);
}
}
void CPRedPart::FocusLost(Environment* ev, ODTypeToken focus, ODFrame* ownerFrame)
{
WeBeHere("\pCPRedPart::FocusLost");
ODUnused(ownerFrame);
if (focus == fMenuFocus)
{
}
}
//-------------------------------------------------------------------------
// Storage protocol
//-------------------------------------------------------------------------
void CPRedPart::CloneInto(Environment* ev, ODDraftKey key, ODStorageUnit* toSU, ODFrame* scope)
{
WeBeHere("\pCPRedPart::CloneInto");
ODStorageUnit* su = fPartWrapper->GetStorageUnit(ev);
ODDraft* draft = su->GetDraft(ev);
ODVolatile(draft);
this->Externalize(ev);
su->CloneInto(ev, key, toSU, scope->GetStorageUnit(ev)->GetID(ev));
if (ev->_major != NO_EXCEPTION)
draft->AbortClone(ev, key);
}
//-------------------------------------------------------------------------
// Frame protocol
//-------------------------------------------------------------------------
void CPRedPart::DisplayFrameRemoved(Environment* ev, ODFrame* frame)
// Removes the frame from the list of display frames.
//
// Called by Frame::Remove().
//
// This method makes whatever other adjustments are necessary
// to deal with removing one of the presentations. This includes
// removing any frames embedded within this display frame.
// Before calling this method, you must ensure that the frame
// has no facets.
{
WeBeHere("\pCPRedPart::DisplayFrameRemoved");
fSession->GetArbitrator(ev)->RelinquishFocusSet(ev, fFocusSet, frame);
}
void CPRedPart::DisplayFrameClosed(Environment* ev, ODFrame* frame)
// Informs a part that one of its display frames is closing.
//
// Called by the frame object.
// The part should remove ╥frame╙ from its list of display frames,
// call Frame::Close() on any frames that are embedded within that
// frame, and then release the frame.
{
WeBeHere("\pCPRedPart::DisplayFrameClosed");
fSession->GetArbitrator(ev)->RelinquishFocusSet(ev, fFocusSet, frame);
}
void CPRedPart::FrameShapeChanged(Environment* ev, ODFrame* frame)
// ÑÑ╩Notifies the part that the frame shape of one of its
// display frames has been changed by its containing part.
//
// Called by Frame::ChangeFrameShape.
//
// The part should take whatever actions are necessary to respond
// to the new shape. It may need to re-layout its content, change
// its used shape, resize its embedded frames, or something else.
// It also has the option of turning around and asking the frame
// for a different frame shape via RequestFrameShape, though it
// must be able to handle the shape it is given. If the size of
// the frame is not sufficient, the part may ask the containing
// part for a continuation frame via CreateEmbeddedFrame.
{
WeBeHere("\pCPRedPart::FrameShapeChanged");
frame->RequestFrameShape(ev, this->MyGetFrameShape(ev, frame), kODNULL);
this->MyAdjustFacets(ev, frame);
frame->Invalidate(ev, kODNULL, kODNULL);
frame->InvalidateActiveBorder(ev);
}
ODShape* CPRedPart::MyGetFrameShape(Environment* ev, ODFrame* frame)
// This is just to centralize the frame shape code. Do it any way
// is best for your part.
{
ODShape* newFrameShape;
if (frame->IsRoot(ev))
newFrameShape = frame->GetFrameShape(ev, kODNULL);
else
newFrameShape = this->MyGetUsedShape(ev, frame);
return newFrameShape;
}
ODShape* CPRedPart::MyGetUsedShape(Environment* ev, ODFrame* frame)
// This is just to centralize the frame shape code. Do it any way
// is best for your part.
{
ODShape* frameShape = frame->GetFrameShape(ev, kODNULL);
RgnHandle shapeRgn = frameShape->GetQDRegion(ev);
frameShape->Release(ev);
Rect rr = (*shapeRgn)->rgnBBox;
short hh = rr.bottom - rr.top;
short ww = rr.right - rr.left;
if (hh > ww) hh = ww;
if (hh < 200) hh = 200;
::SetRect(&rr, 0, 0, hh, hh);
::OpenRgn();
::FrameRoundRect(&rr, 40, 40);
::CloseRgn(shapeRgn = NewRgn());
ODShape* usedShape = frame->CreateShape(ev);
usedShape->SetQDRegion(ev, shapeRgn);
return usedShape;
}
void CPRedPart::MyAdjustFacets(Environment* ev, ODFrame* frame)
// Given a frame, iterate through all of the facets and adjust them
// according to the new frame.
{
ODShape* usedShape = this->MyGetUsedShape(ev, frame);
frame->ChangeUsedShape(ev, usedShape, kODNULL);
usedShape->Release(ev);
ODShape* frameShape = frame->GetFrameShape(ev, kODNULL);
ODFrameFacetIterator* facets = frame->CreateFacetIterator(ev);
for (ODFacet* facet = facets->First(ev);
facets->IsNotComplete(ev);
facet = facets->Next(ev) )
{
facet->ChangeActiveShape(ev, frameShape, kODNULL);
}
frameShape->Release(ev);
}