http://www.newton-inc.com/dev/techinfo/qa/qa.htmnil 'noBackdrop slot to the base view will stop an application from becoming a backdrop application.viewIdleScript. In general, applications should release the CPU now and then so the OS can do clean up operations.self", you can speed things up by doing the lookup explicitly once before executing the loop, and using the call statement to execute the function within the body of the loop.
f1 := {myFn: func() 42};
f2 := {_parent: f1};
f3 := {_parent: f2};
f4 := {_parent: f3};
f5 := {_parent: f4};
f5.test1 := func ()
for i:=1 to 2000 do call myFn with ();
f5.test2 := func() begin
local fn := myFn;
for i:=1 to 2000 do call fn with ();
end
/* executes with a noticeable delay */
f5:test1();
/* executes noticeably faster */
f5:test2();
Use this technique only for functions that don't use inheritance or the self keyword.GetTrapAddress to get a trap's real address and calling it directly to avoid the overhead of trap dispatch.2+3 will be replaced with 5 by the compiler.) In the meantime, you need to write your code as clearly as possible without relying too heavily on the ordering of functions inside expressions.kDebugMode constant in your project and have in your application a statement conditioned by the value of kDebugMode, the NTK compiler removes the entire if/then statement from your application code when the value of kDebugMode is NIL. constant kDebugMode := true; // define in Project Data
if kDebugMode then Print(...); // in application code
kDebugMode constant to NIL, then the compiler strips out the entire if/then statement. if getroot().|MyBaseView:MySIG| then
begin
getroot().|MyBaseView:MySIG|:TestThisView();
local s := getroot().|MyBaseView:MySIG|.BlahSize;
end;installScript, then in the viewSetupFormScript for the application's base view. In your case, you can do some math on the frame returned from GetAppParams to see if the screen is large enough to support your application.Notify to tell the user why your application cannot run.viewBounds so it does not appear, use RelBounds(-10, -10, 0, 0) so the view will be off-screen.viewChildren and stepChildren slots to NIL.AddDeferredSend(self, 'Close, nil) to close the view.protoCloseBox or protoLargeCloseBox then your close box will automatically hide itself if your application is the backdrop application. If you also use newtStatusBar as your status bar proto, the appropriate buttons will shift to fill the gap left by the missing close box. Note that you do not have to use the NewtApp framework to use the newtStatusBar proto.Close and Hide methods so your application cannot be closed.GetUserConfig('blessedApp).viewChangedScript for the view will be called each time the user does something to modify the view. For keyboards, this means the script is called each time the user taps a key. This is the only notification that is provided to indicate the view contents have changed.viewQuitScript or other custom code to explicitly notify the target that the keyboard is going away, but we do not recommend this. (There may be a hardware keyboard attached, a system keyboard may be open, or the user may be writing into your view. It is a mistake to assume that the only way to modify your view is through your own keyboard.)viewIdleScript (or call it from the viewIdleScript.) In the viewChangedScript, if the 'text slot has changed, use :SetupIdle(<delay>) to arrange for the viewIdleScript to be called in a little while.:SetupIdle(<delay>) happens again before the first delay goes by (perhaps because the user typed another key,) the idle script will be called after the new delay. The older one is ignored. SetupIdle resets the timer each time it's called.viewIdleScript return NIL so it won't be called repeatedly.GetRoot():BlessApp(appSymbol) will close the current backdrop application and open the new backdrop application if necessary. Note that appSymbol must be a valid application symbol of a current installed and active application. BlessApp does NOT verify that an application can become the backdrop (for instance, it doesn't check the 'noBackdrop flag for an application). For this reason, BlessApp must only be used on your own applications. See the Newton DTS Q&A, "How to Prevent an Application from Becoming a Backdrop" for more information about the 'noBackdrop flag.BlessApp from within a part's installScript or removeScript. If you want to do something like this, use a delayed call to use BlessApp. stepChildren slot of the base view of the template file. If both the exported and importing template have children, they will both have a stepChildren slot. The result is that the stepChildren slot of the importing prototemplate is masking the one in the exported proto. The instantiated view does not collect all the children from the entire proto chain (though NTK does do this at compile time for user proto templates).stepChildren is to add a viewSetupChildrenScript to either your exported proto template or the importer that collects all of the stepChildren into a runtime stepChildren array.// AFTER setting up stepChildren, views which "import" this proto
// must call inherited:?viewSetupChildrenScript();
exporter.viewSetupChildrenScript := func()
begin
// get the current value of the "extra" kids
// ...unless the importer added NO kids, in which case, these are OURS
local extraKids := stepChildren;
local items := clone(extraKids);
local kids;
local whichFrame := self;
while (whichFrame) do
begin
// get kids, but NOT using inheritance
kids := GetSlot(whichFrame, 'stepChildren);
// copy any extra stepChildren (but if NO extra kids are defined, don't copy twice!)
if kids and kids <> extraKids then
ArrayMunger(items, 0, 0, kids, 0, nil);
// go deeper into the _proto chain (or set whichFrame to nil)
whichFrame := whichFrame._proto;
end;
stepChildren := items;
end;
stepAllocateContext slot.GetRoot().buttons.soft will be non-nil if there is a "soft" button bar, that is, the button bar is located on the drawable screen. GetRoot():LocalBox() returns the rectangle that encloses the screen and the tablet. GetAppParams() returns information about the useful area of the screen, excluding the soft or hard button bar. Used together, this information will allow you to implement any combination of button bar disabling and/or button bar obscuring.KillStdButtonBar. That API is designed for use when you want to actually remove the button bar so you can replace it - probably with a floating slip. It is a fairly expensive call and does a lot of things you don't need if all you want to do is take over the screen. We recommend avoiding that call if possible.) local params := GetAppParams();
if GetRoot().Buttons.soft then
self.viewBounds := OffsetRect(UnionRect(params.appArea, params.buttonBarBounds),
-params.appAreaGlobalLeft, -params.appAreaGlobalTop)
else
self.viewBounds := params.appArea;
appArea and locating the rest of the application within that child.viewSetupFormScript to cover the entire tablet: local params := GetAppParams();
self.viewBounds := GetRoot():LocalBox();
if params.appAreaGlobalLeft then
self.viewBounds := OffsetRect(self.viewBounds, -params.appAreaGlobalLeft, -params.appAreaGlobalTop);
'string. Next, you need to use the global function BinaryMunger to munge an empty string into the VBO. This will properly prepare the binary object to be used as a NewtonScript string.StrMunger as often as needed to copy new string data into the VBO. Here is a code example:// Prepare a VBO to be the string
local myString := GetDefaultStore():NewVBO( 'string, Length("") );
BinaryMunger( myString, 0, nil, "", 0, nil );
StrMunger( myString, StrLen( myString ), nil, "My new string", 0, nil );
// Repeat with more data if necessary...
stdio library function, the NewtonScript StrLen function does not need to traverse the string to determine the string length, so you probably don't need to worry about performance hits from its usage.Stringer global function or the & or && operators, the result is currently a non-VBO string. Be aware that if you accidentally create a very large non-VBO string, the code may throw a "out of NewtonScript heap memory" evt.ex.outofmem exception.clEditView every time some change is made, typing is very slow. So, when should it be saved?AddDelayedCall or AddDelayedSend can be used. The OS also provides AddProcrastinatedSend and AddProcrastinatedCall, which more or less implement the timer-resetting feature for you.viewIdleScript. The viewIdleScript is preferred over AddProcrastinatedCall/Send because of better management of the event queue by the OS. When you call SetupIdle to start an idle timer, any existing idle timer is reset. Procrastinated calls/sends aren't currently implemented by resetting an existing timer, but rather by creating a delayed event which fires for each call and then checking a flag when the timer expires to see if it's the last one.target frame, which is usually a soup entry. The entry layer implements StartFlush to start the timer, and EndFlush is called when the timer expires and which should ensure that the data is saved to the soup.StartFlush equivalent could be implemented something like this: StartFlush: func()
begin
self.entryDirty := TRUE;
:SetupIdle(5000); // 5 second delay
end;
viewIdleScript would look something like this: viewIdleScript: func()
begin
:EndFlush();
nil; // return NIL to stop the idler until next StartFlush
end;
EndFlush equivalent would look something like this: EndFlush: func()
if self.entryDirty then
begin
// getting data from editView may not
// be necessary at this point
myEntry.editViewData := <editView/self>.viewChildren;
EntryChangeXmit(myEntry, kAppSymbol);
self.entryDirty := nil;
end;
EndFlush as a separate method rather than just putting the contents in the viewIdleScript makes it easy to call the method from the viewQuitScript or viewPostQuitScript, to guarantee that changes are saved when the view is closed. (The viewIdleScript may not have been called if the user makes a change then immediately taps the close box or overview or whatever.)DoNotInstall function. This function is called when the package containing the part is activated for the first time as a result of downloading to the unit, putting away to the Extras Drawer, or installation with API functions such as SuckPackageFromBinary or SuckPackageFromEndpoint. The function is not called when the package is installed as a result of card insertion, resetting the unit, or moving the package from one store to another using the Extras Drawer filing. This function is incorrectly mentioned in the Newton Programmer's Guide and Newton Programmer's Reference as DoNotInstallScript. The proper name of the function is simply DoNotInstall. nil, the entire package will not be installed on the device. This provides a convenient way to prevent installation on devices that do not support your package. It's considered bad form to simply fail to install and provide no notification to the user. We recommend at least using GetRoot():Notify(...) to display a message explaining why you are not installing.EnsureInternal anything this function leaves behind to avoid the "Grip of Death" problems (the error with the alert "The package 'MyApp' still needs the card you removed...").SetPartFrameSlot. For example, to create a package that will not install on any unit after the year 2000 (because the world will have ended anyway), do the following: SetPartFrameSlot('DoNotInstall, func()
if Time() >= 50492160 then
begin
GetRoot():Notify(kNotifyAlert, "Millenial",
"This application, and all existence, has expired.");
true; // return non-nil to prevent install
end);
InstallScript will execute in this case, but the part's DoNotInstall function will not.SetPartFrameSlot('labels, '_extensions); InstallScript part method. InstallScript for a form/application part only takes one argument, whereas the InstallScript of an auto part takes two arguments. InstallScript of a form/application part is EnsureInternal'ed, an auto part's InstallScript is not. DeletionScript to my part, it doesn't get called when the user scrubs the package. Why is DeletionScript not called?DeletionScript to your part. The DeletionScript must be defined in a manner different from the part's InstallScript or RemoveScript. You must explicitly set the DeletionScript slot in your part frame using NTK's SetPartFrameSlot global function. Here is an example:SetPartFrameSlot('DeletionScript, func() print("Howdy!") );SetPartFrameSlot for any part slot other than InstallScript or RemoveScript.