http://www.newton-inc.com/dev/techinfo/qa/qa.htm
protoSoupOverview
?HitItem
that gets called whenever an item is tapped. The method is defined by the overview and you should call the inherited one. Also note that HitItem
gets called regardless of where in the line a tap occurs. If the tap occurs in the checkbox, you should do nothing, otherwise you should do something.protoSoupOverview
. So, you can find the actual soup entry by cloning the cursor and moving it.HitItem
method. If the item is selected (the checkbox is not tapped) then the code will set an inherited cursor (called myCursor
) to the entry that was tapped on:func(itemIndex, x, y)
begin
// MUST call the inherited method for bookeeping
inherited:HitItem(itemIndex, x, y);
if x > selectIndent then
begin
// get a temporary cursor based on the cursor used
// by soup overview
local tCursor := cursor:Clone();
// move it to the selected item
tCursor:Move(itemIndex) ;
// move the inherited cursor to the selected entry
myCursor:Goto(tCursor:Entry());
// usually you will close the overview and switch to
// some other view
self:Close();
end;
// otherwise, just let them check/uncheck
// which is the default behavior
end
protoSoupOverview
?protoSoupOverview
. You can draw one in a viewDrawScript
as follows: // setup a cached shape for efficiency
mySoupOverview.cachedLine := nil;
mySoupOverview.viewSetupDoneScript := func()
begin
inherited:?viewSetupDoneScript();
local bounds := :LocalBox();
cachedLine := MakeRect(selectIndent - 2, 0,
selectIndent - 1, bounds.bottom);
end;
mySoupOverview.viewDrawScript := func()
begin
// MUST call inherited script
inherited:?viewDrawScript();
:DrawShape(cachedLine,
{penPattern: vfNone, fillPattern: vfGray});
end;
ValidationFrame
to validate and edit entries in a protoListPicker
. When I edit certains slots I get an error that a path failed. All the failures occur on items that are nested frames in my soup entry. What is going on?validationFrame
in your pickerDef, even if you have no nested entries. Instead, you can provide your own validation mechanism and editors:Validate
method in your picker definitionOpenEditor
method in your picker definitionpickerDef.Validate(nameRef, pathArray)
nameRef
- nameRef to validatepathArray
- array of paths to validate in the nameRefpathArray
in the given nameRef. Accumulate a list of paths that are not valid and return them.pickerDef.ValidateName
and pickerDef.ValidatePager
have been implemented:pickerDef.Validate := func(nameRef, pathArray)
begin
// keep track of any paths that fail
local failedPaths := [];
foreach index, path in pathArray do
begin
if path = 'name then
begin
// check if name validation fails
if NOT :ValidateName(nameRef) then
// if so, add it to array of failures
AddArraySlot(failedPaths, path);
end;
else begin
if NOT :ValidatePager(nameRef) then
AddArraySlot(failedPaths, path);
end;
end;
// return failed paths or empty array
failedPaths;
end;
pickerDef.OpenEditor(tapInfo, context, why)
The arguments and return value are as per OpenDefaultEditor
. However, you need to use this instead of DefaultOpenEditor
.pickerDef.OpenEditor := func(tapInfo, context, why)
begin
local valid = :Validate(tapInfo.nameRef, tapInfo.editPaths) ;
if (Length(valid) > 0) then
// if not valid, open the editor
// NOTE: returns the edit slip that is opened
GetLayout("editor.t"):new(tapInfo.nameRef,
tapInfo.editPaths, why, self, 'EditDone, context);
else
begin
// the item is valid, so just toggle the selection
context:Tapped('toggle);
nil; // Return <nil>.
end;..
end;
The example above assumes that the layout "editor.t" has a New
method that will open the editor and return the associated View.protoFloatNGo
that is a child of the root view created with the BuildContext
function. You are also likely to need a callback to the pickderDef so it can appropriately update the edited or new item. Finally, your editor will need to update your data soup uing an "Xmit" soup method so that the listPicker will update.OpenEditor
example above, the last three arguments are used by the editor to send a callback to the pickerDef from the viewQuitScript
. The design of the callback function is up to you, here is an example:
pickerDef.EditDone := func(nameRef, context)
begin
local valid = :Validate(tapInfo.nameRef, tapInfo.editPaths) ;
if (Length(valid) > 0) then
begin
// Something failed. Try and revert back to original
if NOT :ValidatePager(nameRef) AND
self.('[pathExpr: savedPagerValue, nameRef]) = nameRef then
nameRef.pager := savedPagerValue.pager;
context:Tapped(nil); // Remove the checkmark
end;
else
// The nameRef is valid, so select it.
context:Tapped('select);
// Clear the saved value for next time.
savedPagerValue := nil;
end;
fixedHeight
slot. When I bring up the picker, it is not tall enough to display all the items. Worse, I cannot scroll to the extra items. What is going on?fixedHeight
slot is used for two separate things. Any given pick item can use the fixedHeight
slot to specify a different height. This works fine.fixedHeight
slot of the first pick item (in other words, pickItems[0]
) if it exists. It is as if the following code executes:local itemHeight := kDefaultItemHeight;
if pickItems[0].fixedHeight then
itemHeight := pickItems[0].fixedHeight;
local totalHeight := itemHeight * Length(pickItems);
This total height is used to figure out if scrolling is required. As you can see, this can cause problems if your first item is not the tallest one. The solution is to make sure the first item in your pickItems
array has a fixedHeight
slot that is sufficiently large to make scrolling work correctly. This may be fixed in future revisions of the NewtonOS.fixedHeight
slot in your first item. The default height is not tall enough for most icons. In other words, if you have icons in your pick items, you must have a fixedHeight
slot in the first item that is set to the height of your icon.protoTextList
but they do not appear. How do I get columns?protoTextList
is based on a simple text view which does not support tabs. If you want scrolling selectable columns you can use shapes to represent the rows. If you need finer control, use the LayoutTable
view method.protoNumberPicker
for input. (or) I have used protoNumberPicker
and have encountered a bug/misfeature/problem. What should I use?protoNumberPicker
has several instabilities and bugs. We recommend that you use the DTS sample code "protoNumberPicker_TDS". It provides all of the features of protoNumberPicker
with none of the bugs. It also provides additional functionality that is not in protoNumberPicker
. See the sample code for more detail.protoListPicker
, protoPeoplePicker
, protoPeoplePopup
, or protoAddressPicker
?protoListPicker
. That means that the particular class of nameRef you use must include single selection. In general, this requires creating your own subclass of the particular name reference class.protoListPicker
variant will view. That data definition will include the singleSelect
slot. As an example, suppose you want to use a protoPeoplePopup
that just picks individual people. You could use the following code to bring up a protoPeoplePopup
that only allowed selecting one individual at one time: // register the modified data definition
RegDataDef('|nameref.people.single:SIG|,
{_proto: GetDataDefs('|nameRef.people|), singleSelect: true});
// then pop the thing
protoPeoplePopup:New('|nameref.people.single:SIG|,[],self,[]);
// sometime later
UnRegDataDef('|nameref.people.single:SIG|);
For other types of protoListPickers
and classes, create the appropriate subclass. For example, a transport that uses protoAddressPicker
for emails might create a subclass of '|nameRef.email|
and put that subclass symbol in the class
slot of the protoAddressPicker
.installScript
and removeScript
by registering your dataDef only for the duration of the picker. That would mean registering the class just before you pop the picker and unregistering after the picker has closed. You can use the pickActionScript
and pickCanceledScript
methods to be notified when to unregister the dataDef.protoListPicker
?viewFont
slot in the protoListPicker
itself and have that work (just like you can set viewLineSpacing
slot now). In the meantime, you need a piece of workaround code. Warning: you must set the viewFont of the listPicker AND include this workaround code in the viewSetupDoneScript
:func()
begin
if listBase exists and listBase then
SetValue(listBase, 'viewFont, viewFont) ;
inherited:?viewSetupDoneScript();
end;
This will set the viewFont
slot of the listBase
view to the viewFont
of the protoListPicker
. You cannot rely on the listbase view always being there, hence the test for its existence.lineHeight
slot of the listPicker. Just substitute lineHeight
for viewFont
in the code snippet. The one caveat is that the lineHeight
must be at least 13 pixels.selected
array of a protoListPicker
, it throws a -48402
error. How do I preselect items?protoSoupOverview
?selected
slot:selected
- Required. Initially set to nil
; it is modified by protoSoupOverview
as the user selects and deselects overview items. nil
or the empty array if there is no selection. For example: [[alias: NIL, 66282812, 84, "Names"],
[alias: NIL, 66282812, 85, "Names"]]
protoTextList
after it is displayed. I add an item and scroll to highlight that item. However, the state of the scroll arrows does not correctly get updated. Sometimes it will indicate that there are more items to scroll when it is really at the end of the list.protoTextList
to reset the scroll distance when you update the listItems array. The workaround is to always scroll the list to the top before calling SetupList
when you add items. Then you can scroll the list to where you want it. Note that this workaround is safe to use in Newton 2.1 OS as well. In other words, if you are adding items to a protoTextList
, use this workaround unless your application is Newton 2.1 OS-specific. This method will add a single item to the protoTextList
, set the highlighted item to the new item and scroll if required. It will also make sure the item is unique. AddListItem := func(newItem)
begin
// Insert the item if not already in Array
local index := BInsert(listItems, item, '|str<|, nil, true);
// item must be in the array and index will point to the item.
if NOT index then
begin
:Notify(kNotifyAlert, kAppName, "Duplicate entry.");
return nil;
end;
// workaround a bug in 2.0 that causes the
// scroll arrows to get out of sync
// do this by scrolling to the top
:DoScrollScript(-viewOriginY) ;
self:SetUpList();
// Setting the selection slot will highlight the item
selection := index;
// scroll to show the new item
if index >= viewLines then
:DoScrollScript((index - viewLines + 1) * lineHeight) ;
self:RedoChildren();
return true;
end ;
protoPicker
that I reuse in my application. Sometimes the picker will be blank when I open it. What's happening?ProtoPicker
does not correctly reset the viewOriginY
slot if you display a list that requires scrolling, and then display one that does not require scrolling. The solution is to manually reset the viewOriginY
slot to 0 if you dynamically change the contents of the picker.protoPeoplePicker
displayed names as "last, first", but in Newton 2.1 OS it displays "first last". How can I make protoPeoplePicker
display the original way?nameRefDataDef
for people that will display the name in "last, first" format. The good news is that this workaround will work on both Newton 2.0 and Newton 2.1. The basic steps are:nameRefDataDef
that does the right thingdataClass
slot of your peoplePicker
// create a unique symbol for the the data def
DefineGlobalConstant('kMyDataDefSym,
Intern("nameRef.people.lastFirst:" & kAppSymbol)) ;
DefineGlobalConstant('kMyGetFunc,
func(item, fieldPath, format)
begin
// if this is a person, not a company, modify stuff
local entry := EntryFromObj(item) ;
if fieldPath = 'name AND format = 'text AND entry AND
IsFrame(entry) AND ClassOf(entry) = 'person then
begin
local nameFrame := entry.name ;
if nameFrame AND nameFrame.first AND nameFrame.last then
return nameFrame.last & ", " & nameFrame.first ;
else
return inherited:Get(item, fieldPath, format) ;
end
else
return inherited:Get(item, fieldPath, format) ;
end
) ;
viewSetupFormScript
of the base view of your application: // register my modified people data def
RegDataDef(kMyDataDefSym, {_proto: GetDataDefs('|nameRef.people|),
Get: kMyGetFunc}) ;
viewQuitScript
of the base view of your application: // unregister my modified people data def
UnRegDataDef(kMyDataDefSym) ;
kMyDataDefSym
constant as the value for the dataClass
slot of your protoPeoplePicker
or protoPeoplePopup
protoCountryTextPicker
or default state for protoUSstatesTextPicker
?'default
to the params
frame. The slot must contain the name of the country (protoCountryTextPicker
) or state (protoUSstatesTextPicker
) as a string. For example, if you wanted the protoCountryTextPicker
to default to Canada, you could do the following in the viewSetupFormScript
: // get a writeable copy of the params frame
self.params := Clone(params);
params.default := "Canada";