Question

I've reviewed "View Instantiation" (p. 3-26) in the NewtonScript Programmer's Guide as well as its "The Inside Story on Declare" appendix (p. A-1) and "Declaring Views" section in Programming for the Newton using Macintosh, 2nd ed. I believe I understand it, but I can't quite seem to be able to open a protoFloatNGo window from a click on "About" in my protoInfoButton.

I am starting with the following application (which has a newtStatusBar with a protoInfoButton which does get sent the DoInfoAbout() when "About" is clicked), compiling with tntk, running in Einstein, and exploring data structures with ViewFrame:

infoButtonView := {
    _proto: protoInfoButton,
    DoInfoAbout: func ()
        begin
            :Notify(kNotifyAlert, "MyApp", "DoInfoAbout() got called!");
        end,
    DoInfoPrefs: func ()
        begin
            :Notify(kNotifyAlert, "MyApp", "DoInfoPrefs() got called!");
        end
};

mainView := {
    _proto: protoFloater,
    viewFlags: vApplication + vVisible + vClickable,
    appSymbol: kAppSymbol,
    viewJustify: vjParentFullH + vjParentFullV,
    viewBounds: {left: 16, top: 16, right: -16, bottom: -16},
    stepChildren: [
        {
            _proto: protoTitle,
            title: kAppTitle
        },
        {
            _proto: newtStatusBar,
            menuLeftButtons: [infoButtonView],
            menuRightButtons: []
        },
    ],
};

{
    app: kAppSymbol,
    text: kAppTitle,
    theForm: mainView,
}

Let me see if I can explain my current understanding of the issue... I need to define a protoFloatNGo template/layout, which needs to needs to be instantiated as a view during runtime, and I need to be able to get a reference to that protoFloatNGo view (not template/layout) in infoButtonView:DoInfoAbout() so that I can call :Open() on it.

The protoFloatNGo is nothing special:

{
    _proto: protoFloatNGo,
    stepChildren: [
        {
            _proto: protoTitle,
            title: "About"
        },
    ],
}

My understanding is that I need to set the protoFloatNGo in my mainView so that it's available at runtime, so I have tried putting it in a slot (mainView.aboutLayout), but I get a -48807 (undefined variable) error when I try to access it as either aboutLayout (which I expected) or GetRoot().|MyApp:MyCompany|.aboutLayout. Naturally, that would only get me the layout/template and not the view. So, I've also tried adding it to mainView.stepChildren, but seem to have no way to reference it in GetView() (and this is a documented in the NewtonScript Programmer's Guide and suggests using NTK's "Declare To" functionality).

So, following "The Inside Story on Declare" (which I confirmed by exploring a running copy of Newtoban with ViewFrame), I mimicked the stepAllocateContext/preAllocatedContext structure as follows:

mainView := {
    _proto: protoFloater,
    viewFlags: vApplication + vVisible + vClickable,
    appSymbol: kAppSymbol,
    viewJustify: vjParentFullH + vjParentFullV,
    viewBounds: {left: 16, top: 16, right: -16, bottom: -16},
    stepChildren: [
        {
            _proto: protoTitle,
            title: kAppTitle
        },
        {
            _proto: newtStatusBar,
            menuLeftButtons: [infoButtonView],
            menuRightButtons: []
        },
        {
            _proto: protoFloatNGo,
            preAllocatedContext: 'aboutView,
            stepChildren: [
                {
                    _proto: protoTitle,
                    title: "About"
                },
            ],
        },
    ],
    aboutView: nil,
    stepAllocateContext: ['aboutView, aboutView],
};

Unfortunately, while that compiles, I get a "problem has occurred" when installing the package in Einstein, indicating some unknown problem with the code.

Even if I did get that "Declare To" functionality working, how would I then call it? Could I just do GetRoot().|MyApp:MyCompany|.layoutView:Open();?

Was it helpful?

Solution

Your code looks correct when it comes to the step children and their allocation, but I can't see why it doesn't work... I tried the same approach, but without the newtStatusBar, and that seems to be fine:

kAppSymbol := '|ProtoTest:40Hz|;
kAppTitle := "ProtoTest";
kVersion := "1.0";

infoButtonProto := {
        _proto: protoInfoButton,
        DoInfoAbout: func ()
        begin
                if not Visible(:Parent().aboutView) then :Parent().aboutView:Open();
        end,
        DoInfoPrefs: func ()
        begin
                :Notify(kNotifyAlert, "MyApp", "DoInfoPrefs() got called!");
        end
};

aboutView := {
        preallocatedContext: 'aboutView,
        _proto: protoFloatNGo,
        viewJustify: vjParentFullH + vjParentCenterV,
        viewBounds: {left: 12, top: 0, right: -12, bottom: 220},
        stepChildren: [
                {
                        _proto: protoTitle,
                        title: "About"
                },
        ],
};

mainView := {
        _proto: protoApp,
        title: kAppTitle,
        appSymbol: kAppSymbol,

        stepChildren: [
                {
                        _proto: infoButtonProto,
                        viewJustify: vjParentRightH + vjParentBottomV + vjCenterH + vjCenterV,
                        viewBounds: {left: -39, top: -16, right: -26, bottom: -3}
                },
        ],

        aboutView: nil,
        stepAllocateContext: [
                'aboutView, aboutView
        ],


        viewJustify: vjParentFullH + vjParentFullV,
        viewBounds: {left: 16, top: 16, right: -16, bottom: -16},
};

{
        app: kAppSymbol,
        text: kAppTitle,
        theForm: mainView,
}

Even if I did get that "Declare To" functionality working, how would I then call it? Could I just do GetRoot().|MyApp:MyCompany|.layoutView:Open();?

As you can see in the infoButtonProto, you can refer to the app itself (and all slots it contains) using the :Parent() method (or _parent slot), as the button is a child of the app. The same is true for the aboutView, its parent should also be the app itself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top