// Text of project ListPickerNewEntry written on 5/23/96 at 9:47 AM // Beginning of text file ProjectData /* ** Newton Developer Technical Support Sample Code ** ** ListPicker, The listPicker that uses a user defined soup and ** allows for new entries to be added. ** ** by Stephen Harris, Newton Developer Technical Support ** ** Copyright © 1993-1996 by Apple Computer, Inc. All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction. This sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. You are not ** permitted to modify and redistribute the source as "DTS Sample Code." ** If you are going to re-distribute the source, we require that you ** make it clear in the source that the code was descended from ** Apple-provided sample code, but that you've made changes. */ // This sample demonstates the use of the protoListPicker and a user defined soup and give the // user the option to add new items to the soup. // the app stuff constant kAppTitle := "The List Picker"; //-------------- // Soup stuff constant kSoupName := kPackageName; Constant kSoupIndexes := '[{structure: slot,path: first, type: string}]; // for listPicker query constant kQuerySpec := '{type: index, indexpath: first}; // used by the regUnionSoup function DefConst('kSoupDef, { name: kSoupName, username: kAppName, ownerApp: kAppSymbol, userDescr: "The user soup for the ListPicker sample", indexes: kSoupIndexes }) ; //-------------- // Random entry generator. DefConst('kCanonicalEntry, { first: nil, second: nil, }); DefConst('kRandomDataGeneratorFunc, func() begin local item := clone(kCanonicalEntry); item.first := Capitalize(GetRandomWord(4, 12)); item.second := Capitalize(GetRandomWord(4, 12)); item; end); //-------------- // DeleteScript-> this only gets called when your app is deleted and not // when the card is removed. SetPartFrameSlot('DeletionScript, func() begin //Remove the soup from the stores foreach store in GetStores() do begin local theSoup := store:GetSoup(kSoupName); if theSoup then theSoup:RemoveFromStore(); end; end ); // Install/Remove Scripts InstallScript := func(part) begin RegUnionSoup(kAppSymbol, kSoupDef) ; end; RemoveScript := func(part) begin // unregister autocreation of soup UnRegUnionSoup(kSoupName, kAppSymbol); end; // End of text file ProjectData // Beginning of file editor.t // Before Script for "editBase" // Copyright © 1993-1996 by Apple Computer, Inc. All rights reserved. // this code will be executed before the template is processed editBase := {viewBounds: {left: -4, top: 46, right: 184, bottom: 138}, new: func(nameRef, editPaths, why, pickerDef, callback, context) begin local view := BuildContext(self); view.nameRef := nameRef; view.context := context; view.callback := callback; view.pickerDef := pickerDef; view.editPaths := editPaths; view.reasonForOpen := why; view:Open(); view; end, title: nil, viewSetupFormScript: func() begin // set a title that is what we are doing if reasonForOpen = 'new then title := "New " else title := "Edit " ; title := title & pickerDef.name ; end, callback: nil, context: nil, editPaths: nil, nameRef: nil, pickerDef: nil, reasonForOpen: nil, viewQuitScript: // must return the value of inherited:?viewQuitScript(); func() begin nameRef.first := Clone(first.entryLine.text) ; nameRef.second := Clone(second.entryLine.text) ; Perform(pickerDef, callback, [nameRef, editpaths, context, reasonForOpen]); nameRef := nil ; context := nil ; callback := nil ; pickerDef := nil ; editPaths := nil ; reasonForOpen := nil ; inherited:?viewQuitScript(); // this method is defined internally end, debug: "editBase", _proto: @180 }; _view000 := {viewBounds: {left: -2, top: 0, right: 78, bottom: 16}, _proto: @229}; AddStepForm(editBase, _view000); first := {viewBounds: {left: 8, top: 24, right: 168, bottom: 48}, label: "First", textSetup: func() begin if nameRef.first then Clone(nameRef.first) ; else Clone("") ; end, debug: "first", _proto: @189 }; AddStepForm(editBase, first); StepDeclare(editBase, first, 'first); second := {viewBounds: {left: 8, top: 56, right: 168, bottom: 80}, label: "Second", textSetup: func() begin if nameRef.second then Clone(nameRef.second) ; else Clone("") ; end, debug: "second", _proto: @189 }; AddStepForm(editBase, second); StepDeclare(editBase, second, 'second); constant |layout_editor.t| := editBase; // End of file editor.t // Beginning of text file pickerDef.f //Copyright © 1993-1995 by Apple Computer, Inc. All rights reserved. // listPicker defs // a validation frame is required to support editing. The frame is used // in the pickerDef. DefConst('kValidationFrame, { first: // fieldpath of listPicker display item. { inputProto: { // the line in the defaultOpenEditor _proto: newtLabelInputLine, // protonewtlabelinputline := @422 }, theText: "First", // label for the editLine of the defaultOpenEditor type: 'text, // could be of other type such as 'number or 'shape }, second: { inputProto: { _proto: newtLabelInputLine, }, theText: "Second", type: 'text, }, }); //used to define the pickerDef at compile time. May include all of the slots for the pickerDef. //In the listPicker.pickerDef proto to this DataDef. DefConst('kMySoupDataDef,{ _proto: protoNameRefDataDef, // Required name: "Random Data ", // name at top left of picker // the following stuff is required for validation Validate: func(nameRef, pathArray) begin // keep track of any paths that fail local failedPaths := []; foreach index, path in pathArray do begin // very simple test since each path is // is supposed to be a string // your test may be more complex and call // other methods to verify particular types of data if NOT :ValidateString(nameRef, path) then AddArraySlot(failedPaths, path) ; // return the failedPaths or an empty array end; return failedPaths ; end, // my own utility function to make sure the string is valid // used :Validate above ValidateString: func(nameRef, path) begin // try and get the data from the nameRef local realData := nameRef.(path) ; // if not data in the nameRef, try and get // the entry and get the data from it if NOT realData then begin entry := EntryFromObj(nameRef) ; if entry then begin realData := entry.(path) ; nameRef.(path) := realData ; end ; end ; // valid if the value is non-NIL and is a filled string return realData AND IsString(realData) AND StrFilled(realData) ; end, // provide this method to open an edit slip for // a new or editited item. OpenEditor: func(tapInfo, context, why) begin local valid := :Validate(tapInfo.nameRef, tapInfo.editPaths) ; // check to see if the nameRef is valid to figure out // what to do if (length(valid) > 0) then begin // if not valid, open the editor return GetLayout("editor.t"):New(tapinfo.nameRef, tapInfo.editPaths, why, self, 'EditDone, context) ; end else begin // just toggle the selection and return nil context:Tapped('toggle) ; return nil ; end ; end, // this is a utility method that is not part of the required // methods. Once the editor is closed, this method gets // called so we can update the listPicker appropriately EditDone: func(nameRef, editPaths, context, why) begin // check to see if the edited item is valid if NOT :Validate(nameRef, editPaths) then // not valid so remove the checkmark (if any) context:Tapped(nil); else begin // is valid, so see if editing or a new item if why = 'edit then begin // change the actual entry // an edit occurs when the entry that is clicked // on does not Validate. local entry := EntryFromObj(nameRef) ; if entry then begin entry.first := nameRef.first ; entry.second := nameRef.second ; EntryChangeXMIT(entry, kAppSymbol) ; end ; // The nameRef was valid, so select it. context:Tapped('select); end else begin // a new data item so add entry to soup local newEntry := Clone(kCanonicalEntry) ; newEntry.first := nameRef.first ; newEntry.second := nameRef.second ; GetUnionSoupAlways(kSoupName):AddToDefaultStoreXMIT(newEntry, kAppSymbol) ; // tell the listpicker to update its information context:Update() ; end ; end ; end, }); //************ /* removed validationFrame slot from data def */ // End of text file pickerDef.f // Beginning of file ListPickerSoupNew.t appBase := {viewBounds: {left: 0, top: 0, right: 240, bottom: 320}, viewFlags: 1, viewFormat: 0, declareSelf: 'base, viewJustify: 0, viewSetupFormScript: func() begin //set up app display local b := GetAppParams(); self.viewBounds := RelBounds(b.appAreaLeft, b.appAreaTop, b.appAreaWidth, b.appAreaHeight); if NOT reOrienting then begin //set up soup theSoup := GetUnionSoupAlways(kSoupName); local theCursor := theSoup:Query(kQuerySpec); //make random Entries if there are none in the soup if theCursor:Entry() = nil then :GenerateData(); end; end, theSoup: nil, GenerateData: func() begin // get a local for the array invariant local mySoup := theSoup ; for i := 0 to 19 do mySoup:AddToDefaultStore(call kRandomDataGeneratorFunc with ()); end, viewQuitScript: func() begin //memory reclaim theSoup:= nil; end, ReorientToScreen: func() begin reOrienting := true ; :syncView(); :RedoChildren(); reOrienting := nil ; end, reOrienting: nil, debug: "appBase", viewClass: 74 }; _view001 := {title: kAppTitle, viewBounds: {left: 0, top: 0, right: 150, bottom: 20}, _proto: @229 }; AddStepForm(appBase, _view001); mylistpicker := {viewFlags: 513, viewBounds: {left: 0, top: 20, right: 0, bottom: -70}, viewJustify: 240, pickerDef: { _proto: kMySoupDataDef, //your defined pickerDef class: 'nameRef, //required //the items to be displayed in the listPicker columns: [ // Column 1 { fieldPath: 'first, // field to display in column tapWidth: 120, // width for checkbox & name combined doRowHilite: true, }, // Column 2 { fieldPath: 'second, // field to display in column tapWidth: 0, // width for checkbox & name combined doRowHilite: true, }, ], }, querySpec: kQuerySpec, soupToQuery: kSoupName, selected: nil, suppressFolderTabs: true, suppressCloseBox: true, viewQuitScript: func() begin //when dealing with soups ensure that the listPicker is torn down after closing if //it will be opened again later. selected:= nil; inherited:viewQuitScript(); end, debug: "mylistpicker", _proto: @461 }; AddStepForm(appBase, mylistpicker); StepDeclare(appBase, mylistpicker, 'mylistpicker); _view002 := { buttonClickScript: func() begin :GenerateData(); mylistPicker:Update(); end, text: "Add more Data", viewBounds: {left: 0, top: 6, right: 100, bottom: 24}, viewJustify: 8396950 , _proto: @226 }; AddStepForm(appBase, _view002); _view003 := { buttonClickScript: func() begin whatSelected:open(); end, text: "What is selected", viewBounds: {left: 0, top: 6, right: 100, bottom: 24}, viewJustify: 8396950 , _proto: @226 }; AddStepForm(appBase, _view003); _view004 := {_proto: @401}; AddStepForm(appBase, _view004); whatSelected := {viewBounds: {left: -1, top: 72, right: 106, bottom: 188}, debug: "whatSelected", _proto: @180 }; AddStepForm(appBase, whatSelected); StepDeclare(appBase, whatSelected, 'whatSelected); _view005 := { buttonClickScript: func(textIndex) begin print("selected index " & textIndex); end, viewBounds: {left: 0, top: 0, right: 0, bottom: 116}, viewFont: ROM_fontSystem9, viewLines: 6, viewSetupFormScript: func() begin // call the getSelected fucntion with true to return only the items // that are currently selected' // NOTE: as items are selected nameRef's are created and put in the selected array. // GetSelected returns an array of the selected items and removes all other nameRef's local myArray := []; foreach item in myListPicker:getSelected(true) do AddArraySlot(myArray,(item.first && item.second)); self.listItems := myArray; :SetupList(); end, listItems: nil, viewJustify: 48, viewFormat: 1, useScrollers: true, _proto: @228 }; AddStepForm(whatSelected, _view005); // After Script for "appBase" thisView := appBase; // Copyright © 1993-1996 by Apple Computer, Inc. All rights reserved. constant |layout_ListPickerSoupNew.t| := appBase; // End of file ListPickerSoupNew.t