http://www.newton-inc.com/dev/techinfo/qa/qa.htmprotoSoupOverview?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
endprotoSoupOverview?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 protoPeoplePopupprotoCountryTextPicker 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";