|
MapKit and DataGrids Recap In part 1 of the series we introduced mergExt and started developing an iPhone app using mergMK (MapKit framework external) and MobGUI. We got to the point where the user could add a pin, drag and drop it to relocate and give it a title and subtitle. Last time I also had a simple implementation of an annotation note. I'm going to drop that this time and re-introduce notes later with a full screen user interface for note entry. This time we will lay the foundations for that and use the built in functions for picking a photo to be associated with the annotation. I'll also introduce a custom control that's included in the mergExt suite (mergDataGridScroller) that handles touch scrolling of a DataGrid on iOS and Android. Firstly a little bugfix MapKit won't show the annotation callout unless there is a title so we need to check for the case where the user hasn't entered one in. All we need to do is put a space there instead of nothing. So our new closeCard script for the "Details" card is (remeber I've removed the notes from this card because I want to do something better later): on closeCard if the uText of group "title" = "" then set the annotation["title"] of this cd to " " else set the annotation["title"] of this cd to the uText of \ group "title" end if set the annotation["subtitle"] of this cd to the uText of \ group "subtitle" end closeCard Add a DataGrid to the app using mergDataGridScroller from the DropTools palette. Editing the data grid template group Turn the select grouped controls back off so you can then select and edit the template group. Resize the background graphic to 60 pixels high. Drag an image control on to the background, size it to fit and set it's properties. Relocate the "label" field to the right of the image and centered vertically. Add a line at the bottom of the group using the polygon tool to act as a separator between our documents. Improving the data structure Before we start scripting the behavior of the docs data grid we should make some improvements to the data structure to make things simpler. As the goal is to be able to associate any number of documents with the annotation I have decided to alter the custom property set keys to title,subtitle,coordinate and docs where the docs element is a data grid type array with an index key and label and file child keys. In this way we can set the dgData of group "docs" to tAnnotationA["docs"]. The files will be saved in a folder in the documents directory using the annotation ID as the folder name and the label as the basis of the file name. Click the Row Behavior... button to edit the template group's behavior script. In this tutorial we will make use of the mergDoc functions for returning icons for documents. In a later tutorial we will add thumbnails for photo and video documents. Change the FillInData and LayoutControl commands as follows: global gIDs on FillInData pDataArray set the text of field "Label" of me to pDataArray["label"] put specialFolderPath("Documents")&"/"&gIDs["setnamefromid"] \ [the uAnnotationID of this card]&"/"&pDataArray["filename"] into tPath put mergDocIcon(tPath,line 1 of mergDocIconSizes(tPath)) \ into image "thumb" of me end FillInData on LayoutControl pControlRect local theFieldRect set the points of graphic "line" of me to item 1 of \ pControlRect,item 4 of pControlRect-1&cr&item 3 \ of pControlRect,item 4 of pControlRect-1 put the rect of field "Label" of me into theFieldRect put item 3 of pControlRect - 5 into item 3 of theFieldRect set the rect of field "Label" of me to theFieldRect set the rect of graphic "Background" of me to pControlRect end LayoutControl To handle the fact that there's no annotation id for an annotation before the initial drop we need to setup the custom property set name before we move to the "Details" card and then use that set name when we return. Change the touchEnd script of the Add Pin button on the "Map" card to: global gIDs on touchEnd pId mobGUIUntouch the long id of me # LC5 : new visual effect syntax lock screen for visual effect set the uAnnotationID of cd "Details" to "" put the long seconds into gIDs["setnamefromid"][""] go card "Details" wait for 0 millisecs with messages unlock screen with visual effect "push left very fast" end touchEnd Then change the showMap command to use it when the uAnnotationId is empty: on showMap -- add or update any annotations on the map and save data etc switch the uAnnotationID of cd "Details" case "just opened" break case "" -- create and save a new annotation put gIDs["setnamefromid"][""] into tPropSet break default -- update existing annotation put gIDs["setnamefromid"][the uAnnotationID of cd "Details"] \ into tPropSet -- remove the annotation from the map mergMKDeleteAnnotation the uAnnotationID of cd "Details" -- delete the old relationship (the other one is overwritten -- later) delete variable gIDs["setnamefromid"][the uAnnotationID of cd \ "Details"] end switch put the customProperties["annotation"] of cd "Details" into \ tAnnotationA set the customProperties[tPropSet] of stack "UserData" to \ tAnnotationA save stack "UserData" mergMKSet "visible",true -- add to the map after it's visible so we see the animation if the uAnnotationID of cd "Details" <> "just opened" then -- add the annotation and update the globals put mergMKAddAnnotation(tAnnotationA["coordinate"], \ tAnnotationA["title"],tAnnotationA["subtitle"],true,true,"red",true) \ into gIDs["idfromsetname"][tPropSet] put tPropSet into \ gIDs["setnamefromid"][gIDs["idfromsetname"][tPropSet]] end if end showMap Adding a document to the annotation Use MobGUI to add another button and set it's label to "Add Doc". Choosing the document type In this tutorial we will just add an image but in later tutorials we will add video, audio and text/notes so we will use mergPop to choose which. Set the touchEnd handler script of the Add Doc button to: global gIDs on touchEnd pId mobGUIUntouch the long id of me if the environment = "mobile" then put "Video From Library" into tOptions if mobileCameraFeatures("rear") contains "video" then put ",Video From Camera" after tOptions end if put ",Photo From Library" after tOptions if mobileCameraFeatures("rear") contains "photo" then put ",Photo From Camera" after tOptions end if put ",Note" after tOptions switch mergPopSheet("What type of document do you want to \ add?","Cancel","",tOptions,"black translucent") case "Video From Library" -- TODO break case "Video From Camera" -- TODO break case "Photo From Library" getPhoto "library" break case "Photo From Camera" getPhoto "camera" break case "Note" -- TODO break end switch end if end touchEnd command getPhoto pSource set the visible of the templateImage to false mobilePickPhoto pSource if the result is not "cancel" then ask "Enter a label for the photo:" if the result is not "cancel" then mobileBusyIndicatorStart "square","Saving..." put it into tDoc["label"] put validFileName(tDoc["label"],"png") into \ tDoc["filename"] put the long id of the last image into tImage export tImage to url \ ("binfile:"&specialFolderPath("Documents") \ &"/"&gIDs["setnamefromid"][the uAnnotationID \ of this card]&"/"&tDoc["filename"]) as PNG dispatch AddData to group "docs" with tDoc mobileBusyIndicatorStop end if delete tImage end if end getPhoto function validFileName pLabel,pExtension put (specialFolderPath("Documents")&"/"&gIDs["setnamefromid"] \ [the uAnnotationID of this card]) into tFolder if there is not a folder tFolder then create folder tFolder end if set the defaultFolder to tFolder put replaceText(pLabel,"[^-a-zA-Z0-9_.() ]+","") into \ validFileName if validFileName = "" then put "file" into validFileName end if if there is not a file (validFileName&"."&pExtension) then return (validFileName&"."&pExtension) else put 1 into tNum repeat if there is not a file \ (validFileName&&tNum&"."&pExtension) then return (validFileName&&tNum&"."&pExtension) end if add 1 to tNum end repeat end if end validFileName Updating the card script to handle the docs Here we set the dgData of "docs" group to our saved data in the preOpenCard handler and store the data in the annotation custom property for the map card to use. global gIDs on preOpenCard # mobGUIStart ---> Inserted by mobGUI plugin if "MobGUILib-1334708811870.287842" is not among the lines \ of the stacksInUse then \ start using stack "MobGUILib-1334708811870.287842" mobGUIPreOpenCard me # mobGUIEnd if the uAnnotationID of me <> "" then put gIDs["setnamefromid"][the uAnnotationID of me] into \ tPropSet put the customProperties[tPropSet] of stack "UserData" \ into tAnnotationA set the uText of group "title" to tAnnotationA["title"] set the uText of group "subtitle" to \ tAnnotationA["subtitle"] set the dgData of group "docs" to tAnnotationA["docs"] else set the uText of group "title" to "" set the uText of group "subtitle" to "" if the environment is "mobile" then put mergMKGet("center coordinate") into \ tAnnotationA["coordinate"] end if set the dgData of group "docs" to "" end if -- save extra stuff like "coordinate" set the customProperties["annotation"] of this cd to \ tAnnotationA pass preOpenCard end preOpenCard on closeCard if the uText of group "title" = "" then set the annotation["title"] of this cd to " " else set the annotation["title"] of this cd to the uText of \ group "title" end if set the annotation["subtitle"] of this cd to the uText of \ group "subtitle" set the annotation["docs"] of this cd to the dgData of group \ "docs" end closeCard Presenting the document preview The next thing we want to do is preview a selected document. For this we will use the mergDoc command mergDocShowPreview and set the script of the "docs" data grid to: global gIDs on selectionChanged pHilitedIndex put the dgDataOfIndex[pHilitedIndex] of me into tData mergDocShowPreview specialFolderPath("Documents") \ &"/"&gIDs["setnamefromid"][the uAnnotationID of this card] \ &"/"&tData["filename"] end selectionChanged What next? Last time I promised I would use mergAV to record and pick video. I didn't quite get there in this tutorial but it will be the first thing we do in part 3.
|
Tweet
|