Hi all RB rugrats (oops, I mean 'guru's) :)
Here's an odd case - hoping someone can suggest a better 'hack'.
Let's say (in C++) that I have a struct
struct myGameData
{
// whatever...
};
typedef struct myGameData MyGameData,*MyGameDataPtr;
and I have a window, 'wndAddEditGameData' that has one property,
'MyGameDataPtr *gameDataHndl' and a method, 'void Display();'. I can
set it up like
#include "mygame.h"
int main(int argc, char *argv[])
{
// Option 1; add mode. wndAddEditGameData checks the pointer,
realizes its nil, and creates a data structure
// for us dynamically
MyGameDataPtr mgd;
wndAddEditGameData *w;
mgd = nil; // just to be sure; I'm really anal about these sorts of
things!
w = new wndAddEditGameData;
w.GameDataHandle = &mgd;
w->Display();
// user sets the properties for a new 'struct MyGameData' - pointed
to by mgd; When done, we return here.
SaveMyGameData(mgd);
// Option 2; edit mode. wndAddEditGameData checks the pointer, sees
that it already exists, and allows us to
// edit the information already there.
mgd = LoadMyGameData("Macintosh
HD:Users:wsquires:Documents:XCode:MyGame:mygame.dat");
if (mgd != nil)
{
w = new wndAddEditGameData;
w.GameDataHandle = &mgd;
w->Display();
// as before, user changes some (or maybe none) of the properties
of the MyGameData structure.
SaveMyGameData(mgd);
}
else
{
// Error!
}
}
What's the recommended OO way of doing this in RB? The slickest
thing I can think to do is define a simple wrapper class for the
"Class MyGameData", and make an RB Window with a property of type
<reference-to-wrapper-class-for-class-MyGameData> (the
wndAddEditGameData window.)
Another, but less preferred way (that I've done in the past),
would be to make sure the "Class MyGameData" implements a deep copy
method, "Clone() As MyGameData", then - when you assign the referene
to the public property of the window (an "Assigns" sub) - it checks
the reference for nil.
If the reference was nil, it creates one for us. If the reference
was non-nil, it'll call .Clone() on the reference to get a separate
object (in case the user aborts). In any case, the window will
implement a getter method that returns a reference to a newly created
MyGameData object. The caller will then check another property of the
window, "ButtonClicked As Integer" to see if the user accepted or
cancelled. If accepted, then .Clone() will be called on the result so
it can be put back into the original object reference available to
the calling code. Otherwise, will just dispose of the result.
* Note that - in this implementation - the copy is needed so that the
object we get back from wndAddEditGameData is always a unique object
and not simply a referene to the original (in edit mode), as the
calling code will need to check the user interaction with the dialog
to see if they cancelled or not. In the C++ version, this would not
be necessary as the window would hide all the details including the
copy-back when the user accepts. (i.e. the calling code never has to
worry about the user interaction; whatever is in the data structure
is what the user desired.)
It'd be nice if RB had a syntax like:
Dim myData As MyGameData
Dim myDataRef As ByRef MyGameData = &myData
Dim w As wndAddEditGameData
// option 1 - add
myData = nil
w = New wndAddEditGameData()
w.GameDataHandle = myDataRef
w.Display()
// myData now holds a reference to a MyGameData object even if it
didn't before
myGameData.Save()
// option 2 - edit
myGameData = New MyGameData()
myGameData.Load("mydata.dat")
w = New wndAddEditGameData()
w.GameDataHandle = myDataRef
w.Display
// and, again, myData now holds a reference to a (possibly edited)
MyGameData object.
myGameData.Save()
Note the "ByRef" and "&" in the Dim statement! For simplicity's
sake, this syntax would only work with object reference data types,
not simple data types like Integer, String, etc...
_______________________________________________
Unsubscribe or switch delivery mode:
<http://www.realsoftware.com/support/listmanager/>
Search the archives of this list here:
<http://support.realsoftware.com/listarchives/lists.html>