System for writing main memory address of object to secondary storage when storing object and reading main memory address of object when retrieving object from secondary storage5805896Abstract A method and system for interconnecting software components. In a preferred embodiment, the present invention instantiates an event object. The event object includes message information describing the message and a dispatching member function for invoking a member function of a target object passing the message information. A message is passed by invoking the dispatching member function of the event object passing an identifier to a target object and an identifier of a member function of the target object. The dispatching member function invokes the identified member function of the identified target object passing the event information as an actual parameter. The event object is preferably of a derived class that inherits a base class. The base class provides common event behavior, while the derived class provides behavior specific to a type of message. Claims I claim: Description TECHNICAL FIELD
CODE TABLE 1
______________________________________
class CONNECTION
{ CObject *ptarget;
ULONG pmftarget;
ULONG pmfsource;
class CObject
{
boolean isRecursing;
CONNECTION connectionArray›10!;
int connectionCount;
virtual boolean NotifyEvent (CEvent *pevent, CObject
*psource, ULONG pmftarget);
boolean InformTargets(CEvent *pevent, ULONG
pmfsource);
void AddTarget(CObject *ptarget,
ULONG pmftarget, ULONG
pmfsource);
virtual void Serialize(CArchive &ar);
virtual VOID WriteConnectionArray(CArchive
&ar);
virtual VOID ReadConnectionArray(CArchive
&ar);
virtual VOID SerializeObjectData(CArchive &ar);
};
BOOL CObject::NotifyEvent (CEvent *pevent, CObject *psource,
ULONG pmftarget)
{
BOOL ret;
if (isRecursing) return FALSE;
isRecursing = TRUE;
if (pevent -> IsKindOf(CValueEvent))
ret ((CValueEvent*)pevent)->Dispatch(psource, this, pmftarget);
else if
.
.
.
else return FALSE;
isRecursing = FALSE;
return ret;
}
BOOL CObject::InformTargets(CEvent *pevent, ULONG pmfsource)
{
for (i = 0; i < connectionCount; i++)
{
if (connectionArray›i!.pmfsource == pmfsource)
connectionArray›i!.pmftarget->NotifyEvent(pevent, this,
connectionArray›i!.pmftarget);
}
}
void CObject::AddTarget(CObject *ptarget, ULONG pmftarget, ULONG
pmfsource)
{
i = connectionCount++;
connectionArray›i!.ptarget = ptarget;
connectionArray›i!.pmftarget = pmftarget;
connectionArray›i!.pmfsource = pmfsource;
}
______________________________________
The programming system adds connections to a run-time object by invoking the member function AddTarget provided by the connection manager. The programming system invokes the AddTarget member function of the source object whenever a programmer connects two objects. The member function and AddTarget is passed a pointer to the target object, a pointer to the target member function (representing the input port), and a pointer to a source member function (representing the output port). The member function AddTarget adds an entry to the connectionArray of the source object corresponding to the passed parameters. In a preferred embodiment, the connections are stored not as data members of the CObject, but rather are stored in a heap that is shared by all run-time objects. In this way, the storage overhead for each object can be minimized. A message is sent to a target object in the following manner. The source object instantiates an event object and stores event information in the event object. The source object invokes the member function InformTargets of its connection manager passing the event object and a pointer to the source member function. For each connection for that output port (source member function), the connection manager invokes the member function NotifyEvent of target object passing the event object, a pointer to the target member function, and a pointer to the source object. The member function NotifyEvent invokes the member function Dispatch of the event object passing a pointer to the source object, a pointer to the target object, and a pointer to the target member function. The member function Dispatch invokes the target member function of the target object passing the stored event information as actual parameters. An event object encapsulates the message information in a way that is transparent to the connection manager. Thus, the connection manager can control the invoking of target member functions passing arbitrary parameters. FIG. 7 is a flow diagram illustrating the flow of control of sending a message from a source object to a target object. A source member function 710-714 of the source object instantiates an event object in step 711. In step 712, the source member function stores the event information in the event object. In step 713, the source member function invokes the member function InformTargets of the connection manager passing a pointer to the event and the source member function. In step 721, the member function InformTargets loops determining which entries in the connection array correspond to the source member function. When an entry is found, the member function InformTargets invokes the member function NotifyEvent of the target object passing a pointer to the event, a pointer to the source object, and a pointer to the target member function. In step 731, the member function NotifyEvent of the target object invokes the member function Dispatch of the event passing a pointer to the source object, a pointer to the target object, and pointer to the target member function. In step 741, the member function Dispatch invokes the target member function passing the event information stored in the event object. The target member function processes the event information in step 751. The target member function then returns, which causes the member functions Dispatch, NotifyEvent, and InformTargets to return to the execution of the source member function. The use of an event object allows the connection manager to invoke input member functions with arbitrary parameters. Each prototype for a input member function has its own implementation of the event class to handle the event. The source object instantiates the appropriate class of event object. For example, the input member function ValueIn is passed an integer. Thus, an event class is implemented that contains an integer data member to store the value. The member function Dispatch of the event class invokes a passed target member function passing the stored value. An event class may be implemented for each different prototype of a target member function. For example, if the event information includes both an integer and a string, then an event class can have a data member for the integer and another for the string. The member function Dispatch of the event class invokes a passed target member function passing the integer and the string as parameters. Code Table 2 contains pseudocode that describes the event classes. Each event class derives from the class CEvent. The event class CIntEvent is used to pass information stored as an integer to a target member function. The member function Dispatch is passed a pointer the target object and a pointer to the member function. The member function Dispatch invokes the target member function by the following statement: (ptarget->*(LongToMember(pmftarget))) (numValue) The event class CActionEvent is used to pass messages with no corresponding data, and the event class CStringEvent is used to pass messages with string data.
______________________________________
class CEvent
public:
CEvent();
virtual BOOL Dispatch (CObject *psource, CObject *ptarget,
ULONG pmftarget)=0;
}
class CActionEvent : public CEvent
{
public:
virtual BOOL Dispatch (CObject *psource, CObject *ptarget,
ULONG pmftarget)
{(ptarget->*(LongToMember(pmf)))()};
}
class CIntEvent : public CEvent
{
public:
INT numValue;
virtual BOOL Dispatch (CObject*psource, CObject *ptarget,
ULONG pmftarget)
{(target->*(LongToMember(pmftarget)))(numValue)};
}
class CStringEvent : public CEvent
{
public:
STRING stringValue;
virtual BOOL Dispatch (CObject *psource, CObject *ptarget, ULONG
pmftarget);
{(ptarget->*(LongToMember(pmftarget)))(stringValue)};
}
______________________________________
Code Table 3 contains pseudocode for a sample scroll bar object corresponding to a scroll bar component. The scroll bar object is defined by class CScrollbar, which inherits the connection manager (class CObject). The class contains data members to store the current value of the scroll bar, a large and small increment for the scroll bar, and the minimum and maximum values for the scroll bar. The class also contains the member function to set and retrieve the current value, to receive messages from the parent window of that scroll bar, and to effect various scroll bar behaviors. The scroll bar component has an input function member (value) with one parameter and an output function member (value) with no parameters. The constructor CScrollbar registers the scroll bar with the operating system and initializes its data members. The member function HandleParentMsg receives messages from the parent window and dispatches the message. For example, if the member function HandleParentMsg is passed a message that the scroll bar event line up (SB LINEUP) has occurred, then the member function invokes the member function LineUp. The member function LineUp instantiates a CActionEvent object, sets a pointer to the member function LineUp, and invokes the member function InformTargets of the connection manager. The member function LineUp then invokes the member function value passing a new value for the scroll bar. The member function value receives the new value. If the new value is different than the current value, then the member function adjusts the slider, instantiates a CIntEvent object, sets the event object to the new value, sets a pointer to the member function value (to identify the source member function), and invokes the member function InformTargets of the connection manager. The member function minimum illustrates a member function of an object that does not cause a message to be sent to target objects, that is, it does not correspond to an output port. The member function minimum, however, may correspond to an input port. In one embodiment, a member function could correspond to both an input and an output port (a bidirectional port). The member function can be invoked to receive a message and then send a message to other target objects. In a preferred embodiment, the present invention is implemented to execute under the Windows operating system developed by Microsoft Corporation. The Windows operating system is described in "Programming Windows" written by Charles Petzold and published by Microsoft Corporation, which is hereby incorporated by reference.
CODE TABLE 3
______________________________________
class CScrollbar : CObject, CWindow
INT m.sub.-- largeChange;
INT m.sub.-- smallChange;
INT m.sub.-- value;
INT m.sub.-- minimum;
INT m.sub.-- maximum;
BOOL m.sub.-- isVert;
CScrollBar();
CScrollBar(const VRect &pos, CWindow *parent,
boolean isVert);
virtual INT largeChange();
virtual VOID
largeChange(INT);
virtual INT smallChang();
virtual VOID
smallChange(INT);
virtual INT value();
virtual VOID
value(INT);
virtual INT minimum();
virtual VOID
minimum(INT);
virtual INT maximum();
virtual VOID
maximum(INT);
virtual VOID
lineUP();
virtual VOID
lineDown();
virtual VOID
pageUP();
virtual VOID
pageDown();
virtual LONG
HandleParentMsg(HWND hwnd, unsigned wm,
WORD wParam, LONG
IParam);
}
CScrollBar::CScrollBar(const VRect &pos, CWindow *parent,
BOOL isVert)
DWORD style;
if (isVert)
style = WS.sub.-- CHILD .vertline. SBS.sub.-- VERT;
else
style = WS.sub.-- CHILD .vertline. SBS.sub.-- HORZ;
m.sub.-- isVert = isVert;
CWinWindow::Init(
parent,
NULL,
0L,
"SCROLLBAR",
"",
style,
pos.left,
pos.top,
pos.right - pos.left,
pos.bottom - pos.top,
NULL,
NULL);
smallChange(1);
largeChange(10);
minimum(0);
maximum(100);
value(0);
}
VOID CScrollBar::lineUp()
{
CActionEvent evt;
VOID (ScrollBar::*mfp)() = &CScrollBar::lineUp;
InformTarget(&evt, MemberToLong(mfp));
value(m.sub.-- value-m.sub.-- smallChange);
}
VOID CScrollBar::value(INT theValue)
{
if (theValue < m.sub.-- minimum)
theValue = m.sub.-- minimum;
if (theValue > m.sub.-- maximum)
theValue = m.sub.-- maximum;
if (m.sub.-- value |= theValue)
{
m value = theValue;
if (m.sub.-- hwnd |= NULL)
SetScrollPos(GetHwnd(), SB.sub.-- CTL, m.sub.-- value,
TRUE);
CIntValue numEvent;
INT (CScrollBar::*mfp)() = &CScrollBar::value;
numEvent.numValue = m.sub.-- value;
InformTargets(&numEvent,
(ULONG)MemberToLong(mfp));
}
}
VOID CScrollBar::minimum(INT theMinimum)
{
m.sub.-- minimum = theMinimum;
if (m.sub.-- hwnd |= NULL)
SetScrollRange(GetHwnd(), SB.sub.-- CTL, m.sub.-- minimum, m.sub.--
maximum,
TRUE);
if (m.sub.-- value < the Minimum)
value(theMinimum);
}
LONG ScrollBar::HandleParentMsg( HWND hwnd,
unsigned wm,
WORD wParam,
LONG IParam)
{
switch(wm)
{
case WM.sub.-- HSCROLL:
case WM.sub.-- VSCROLL:
switch(wParam)
{
case SB.sub.-- LINEUP:
lineUp(); break;
case SB.sub.-- LINEDOWN:
lineDown(); break;
case SB.sub.-- PAGEUP:
pageUp(); break;
case SB.sub.-- PAGEDOWN:
pageDown(); break;
case SB.sub.-- TOP: value(minimum()); break;
case SB.sub.-- BOTTOM
value(maximum()); break;
case SB.sub.-- THUMBTRACK:
case SB.sub.-- THUMBPOSITION:
value(LOWORD(IParam));
break;
case SB.sub.-- ENDSCROLL:
break;
}
default: break;
}
return CWinWindow::HandleParentMSG(hwnd, wm, wParam, IParam);
}
______________________________________
In a preferred embodiment, the programming system persistently stores the run-time objects of a visual program. The programming system maintains a pointer to each run-time object corresponding to a component. To store the program, the programming environment invokes a member function Serialize (provided by the connection manager of each object). The member function Serialize writes the connection array to the persistent storage and invokes the member function SerializeObjectData to write the object specific data to the persistent storage. The member function SerializeObjectData of the connection manager would typically be overridden by the run-time object corresponding to the component. For example, the member function SerializeObjectData for the scroll bar object writes each data member to persistent storage. Similarly, each object has corresponding member functions to retrieve the persistent stored data. When storing and retrieving data, the programming system needs to map the memory address of each pointer to its persistently stored object data. When the object data is retrieved, the pointers in the connection array need to be mapped to their new memory locations. In a preferred embodiment, each component has a corresponding editor object which controls the placement, movement, and connection to the component. A standard interface (CEditor) to the editor object is provided. The CEditor object provides a standard mechanism (1) for displaying the available ports and the current connections, (2) for selecting an available port, (3) for connecting a port to another port, and (4) for moving the component. The implementor of a component preferably implements an editor object that inherits the CEditor interface. When a programmer selects a component, the programming system instantiates both the run-time object and an editor object for the component. FIG. 8 is a block diagram of data structures of a CEditor object. The CEditor object 802 contains a pointer to a list of available ports (mPortList), a pointer to a user interface editor object (mEditorUI), a pointer to the run-time object corresponding to the component (mSubject) , a pointer to a list of child editor object (mChildEditors), and a pointer to a parent editor (mParent). Each port is described by a CEditPort object 808. A CEditPort object contains a pointer to the associated CEditor object (mOwnerEditor), a pointer to a list of input ports to which the port is connected (mConnectedPorts), status information (mStatus), and pointer to member functions identifying the input and output portions of the port (mValueIn and mValueOut) as pointers to member functions. The CEditorUI object 812 contains member functions to control moving the component on the display and displaying available ports and connections. A component may contains child components. For example, a window component (parent component) may contain a scroll bar component. The CEditor object for the window contains pointers to each child CEditor object. The visual programming environment tracks the first level of parent components. Each CEditor object tracks its child CEditor objects. When an event occurs (e.g. mouse button down), the programming environment passes the event to the appropriate first level component. The first level component is responsible to passing the event on the appropriate child component. Code Table 4 is pseudocode for the class CEditor. The CEditor class inherits the CObject class. This inheritance allows connections between CEditor objects to be controlled by the connection manager. The CEditor objects are, thus, connected in a manner similar to the way the run-time objects are connected. The CEditor object includes a constructor and member function to delete an object.
CODE TABLE 4
______________________________________
class CEditor:
public CObject
public:
CEditor(CEditor* pEditor, CObject* pSubject);
virtual VOID ObjectDeleted(CObject* object);
virtual VOID PortChanged(CEditPort* port);
VString mName;
private:
CEditPortListPtr mPortList;
CEditorUIPtr mEditorUI;
CObjectPtr mSubject;
CEditorListPtr mChildEditors;
CEditorPtr mParent;
};
VOID CEditor::ObjectDeleted(CObject* object)
{
for each CEditPort port1 in mPortList
if (port1 is connected)
for each CEditPort port2 in mConnectedPorts of port1
if (port2.mSubject == object)
port1->Disconnect(port2)
RemoveTarget(object);
mSubject->RemoveTarget(object);
for each CEditorUI eui in mEditorUIList
eui->RemoveTarget(object);
};
______________________________________
Code Table 5 contains pseudocode defining CEditorUI class. The CEditorUI class provides a standard mechanism for editing connections between components and movement of components. When a programmer selects to add a component to a visual program, the programming system instantiates the object, an CEditorUI for the object, and a CEditor object for the object. In a preferred embodiment, the programmer can move a component by clicking on the component. A tracker box is drawn and the user can then drag the component to a new position.
CODE TABLE 5
______________________________________
class CEditorUI: public CObject, CWindow
public:
virtual void Draw(const VRect& rectUpdate);
virtual BOOL OnMouseStart(CUserEvp *, VPoint, INT,
INT);
virtual BOOL OnMouseDrag(CUserEvp *, VPoint, BOOL);
virtual BOOL OnMouseEnd(CUserEvp *, VPoint, BOOL);
virtual void PositionChange();
BOOL showTracker;
VPoint startSize;
VPoint startPoint;
WORD dragMode;
virtual BOOL MakeStdUI(CEditor*, CWindow*);
virtual BOOL NotifyEvent(CEvent* ev,
CObject* sender,
ULONG action);
CPopMenuPtr m.sub.-- popup;
CPropertyDialogPtr
m.sub.-- dialog;
private:
CEditorPtr mEditor;
BOOL mIsActive;
};
______________________________________
The programming system invokes the member function Draw to request the component to draw a tracker box. The programming system invokes the member function OnMouseStart to indicate that object is being selected, the member function OnMouseDrag to indicate the new position of the tracker, and the member function OnMouseEnd to indicate that the tracking is complete. The member function OnMouseEnd invokes the member function PositionChange to pass the new position to the CEditorUI object that is specific to the component (e.g., scroll bar). The member function MakeStdUI initializes a standard user interface for the component. The standard user interface includes a menu for selecting to delete the component, to move or size the component, or to change properties of the component. The CEditorUI provides a standard dialog for displaying available ports and current connections. For example, a list of available ports would be
______________________________________
Name Type Input Member
Output Member
______________________________________
Position CIntEvent 6 7
Pageup CActionEvent
11 12
______________________________________
Code Table 6 contains pseudocode describing the CEditPort class. This class provides member functions to manage the actual connection between components. When two ports are selected for connection, the programming system invokes the member function Connect of the output port passing the input port. The member function Connect adds the target object to the connection array of the source object and adds the input port to the list of connections for the editor object.
CODE TABLE 6
______________________________________
class CEditPort: public CObject
public:
virtual Connect(CEditPort*
BOOL OtherPort);
virtual Disconnect(CEditPort*
BOOL OtherPort);
private:
VString mName;
CEditorPtr mOwnerEditor;
CObjectPtr mSubject;
CEditPortListPtr mConnectedPorts;
BOOL mIsConnected : 1;
BOOL mIsOutput : 1;
BOOL mIsInput : 1;
BOOL mCanRead : 1;
BOOL mCanWrite : 1;
CObjectPtr mValueIn;
CObjectPtr mValueOut;
};
BOOL CEditPort::Connect(CEditPort*
OtherPort)
{
mSubject->AddTarget(
Otherport->mSubject,
OtherPort->MValueIn,
this->MValueOut);
mIsConnected = TRUE;
mConnectedPorts->Add(OtherPort);
return TRUE;
}
______________________________________
Code Table 7 contains pseudocode for an implementation of the CEditor class for a scroll bar component. The implementation provides a constructor for the CEScrollBar class that inherits the CEditor class. The Constructor instantiates a CEditPort object for each port for the scroll bar component. In this example, the ports are "value" and "LineUp." The port value is a bidirectional port, that is, the member function value can be connected to an input and output port. The constructor also creates a CEScrollBarUI object. Code Table 8 contains pseudocode for the EScrollBarUI class.
CODE TABLE 7
______________________________________
class CEScrollBar : CEditor
{ CEScrollBar(CEditor* pParentEditor,
CWindow* pParentWindow,
CObject* pSubject);
};
CEScrollBar::CEScrollBar(CEditor* pParentEditor,
CWindow* pParentWindow,
CObject* pSubject)
: CEditor(pParentEditor, pSubject)
CEditPort* pp;
void (CScrollBar::*mfp3)();
name(**);
{
INT (CScrollBar::*mfp1)() = &CScrollBar::value;
void (CScrollBar::*mfp2)(INT) = &CScrollBar::value;
pp = new CNumEditPort(this, "Value");
pp->isOutput(TRUE);
pp->valueOut( (CObject*)MemberToLong( mfp1 ) );
pp->isInput(TRUE);
pp->valueIn( (CObject*)MemberToLong( mfp2 ) );
pp->canRead(TRUE);
pp->canWrite(TRUE);
portList()->Add(pp);
}
pp = new CEditPort(this, "Line Up");
pp->isInput(TRUE);
pp->valueIn( (CObject*)MemberToLong( mfp3 =
&CScrollBar::lineUp ) );
portList()->Add(pp);
CEScrollBarUI* ui = new CEScrollBarUI(this,
pParentWindow);
editorUIList( new CEditorUIList );
editorUIList()->Add( ui );
}
______________________________________
FIG. 9 is a block diagram illustrating a computer system for implementing the present invention. The computer system 901 includes central processing unit 902, memory 903, storage 904, display 905, and input device 906. In a preferred embodiment, objects are instantiated in memory and persistently stored to storage. Visual programs output data to the display and input data from the input device. Although the present has been described in terms of a preferred embodiment, it is not intended that the invention be limited to this embodiment. Modifications within the spirit of the invention will be apparent to those skilled in the art. The scope of the present invention is defined by the claims which follow.
|
Same subclass Same class Consider this |
||||||||||
