Creating a simple stock control application for the iPad
Mobile devices are changing the way that business works, from how we interact to with our customers to how we manage our stock. LiveCode is a simple, easy to learn tool that lets people in all aspects of business get involved in this new mobile revolution.
This simple, easy to follow tutorial shows how to make a basic management application for the iPad. The app includes all the information normally stored in a standard stock management system and makes it accessible in the mobile space.
See how to create the interface, use iOS gestures and save the app on your iOS device. Full iOS features are supported and the data is directly editable and easily navigable.
You can find the stack used in this lesson along with the images it uses here: https://tinyurl.com/ydx9bx7f
The Final Product
When you have completed this sample application you will have a fully skinned and working stock management application that allows users to add, edit and delete items.
Before Starting
Before you start on your app you need to ensure LiveCode is set up to develop for iOS devices. There are lessons on getting set up as an iOS developer at
What do we want to be able to do?
The first thing we need to think about is what we want the app to be able to do, what functionality do we need? In this case we are keeping it very simple, all we want to do is store information about our stock. We need to be able to add new stock items, delete items and update information. We would also like to be able to go to a vendor's website and automatically calculate the profit and value of our stock.
So the information we want to store for each stock item is:
name, description, image, vendor, vendor website, stock level, cost price and sale price
And the functionality we want is:
add item, edit item, delete item, go to vendor website, sell item, move between items, calculate the profit on an item, calculate the value of our stock
Of course we also want our data to be persistent between uses of the app so we need to save the data on the device.
Creating the Stack
The first thing to do is to create a new stack by selecting New Stack from the File menu, open the Property Inspector for the stack using the Inspector button (1) and set the name of it to Stock and the label to Stock Management.
Then select the Size and Position tab (2) and set the width of the stack to 768 and the height of the stack to 1024. This is the screen size of an iPad in portrait orientation when the status bar is not showing, if you want to show the status bar in your app then set the height of your stack to 1004 to allow 20px for the status bar. Turn off the resizable property (3).
Note: in this tutorial we will only allow Portrait orientation. When you have finished this sample application you could expand it to support landscape orientation.
Adding Controls to the Stack
Now we need to add fields to the stack to allow us to enter and display details and an image are to allow us to select a picture. We also need buttons to go to the vendor website, add a new stock item, delete a stock item, and sell a piece of stock.
You build your interface by dragging controls from the Tools Palette to the stack, you can select and drag controls on the stack to try different layouts.
Once you have added the controls to your stack use the Property Inspector to name them, for example I have named field 1 "description label" and field 2 "description". Giving controls memorable names makes them easier to refer to later in code.
Launching the Vendor Site
To go to the website specified in the "Vendor Website" field we can use the LiveCode launch url command.
Select the "Go to Vendor Website" button, open the Script Editor for the button and set the script of the button to
on mouseUp
put field "vendor website" into tVendorWebsite
launch url tVendorWebsite
end mouseUp
Selecting an image using MobilePickPhoto
It is simple enough to use fields to enter text data but what do we do about selecting an image? For this task we will use the mobilePickPhoto command.
The command "mobilePickPhoto" takes a single parameter that defines what type of choice to use, once the user has chosen an image the selected image appears on the stack and can be manipulated.
In this case we want the user to select in image from their library so we use the command mobilePickPhoto "library"
Using the Edit tool(1) select the image control (2), open the script editor (3) and set the script of the image (4) to
on mouseUp
## When mobilePickPhoto is used the new, chosen image is placed onto the stack
## we want it to appear in the image area
## and not resize
set the rect of the templateImage to the rect of me
set the lockLoc of the templateImage to true
mobilePickPhoto "library"
if the result is empty then
# If the result is empty you know the user has chosen an image and you can start working with it.
end if
## The new image will be the "last" image ## We get the text of it, set the text of the stock image and then delete the "last" image
set the text of me to the text of the last image of this card
delete the last image of this card
end mouseUp
This will only work on an iOS device so we will test in in the simulator later, and then on a device.
How will the Information be Stored?
A LiveCode stack is made up of a series of cards. We will use one card per item, each card will store the information on a particular piece of stock. We can add new items by adding card, delete items by deleting a card and navigate through the stack by moving between cards.
Adding a New Item
To add a new item we want to add a new card to the stack. The new card should contain all the controls we have set up ready to be populated with the information about the item.
There is a simple way to do this in LiveCode. By grouping the controls together and setting the Behave Like a Background property of the group to true the controls will automatically be added to any new cards that are created.
To do this select all the controls, choose the Group option in the menubar (1), then select the group, name it "controls" (2) and set the Behave Like a Background property to true (3).
The only control we can't include in the group is the image control, this is because the image data is not distinct for each card when contained in a background so we will copy the image to each new card separately.
Scripting the New Button
Now that we have created our background we need to script the New button to create a new card and create an image area. Select the New button, open the script editor and set the script of the button to
on mouseUp
newEntry
end mouseUp
The newEntry handler is on the stack script, which can be opened from the Object menu
on newEntry
## Add a new card
## This will create a new card with the controls group on it
create card
## The long name is a unique identifier
put the long name of it into tNewCard
## We need to create an image separately on the new card as image data is shared
copy image "stock image" of card 1 to tNewCard
set the text of image "stock image" of tNewCard to empty
## Put the initial text into the fields
send "resetControls" to group "controls" of tNewCard
## Go to the new card using a visual effect
visual effect push left
go to tNewCard
## Put the cursor in the name field
focus on field "name" of group "controls" of tNewCard
select after field "name" of group "controls" of tNewCard
end newEntry
Moving between records
Once there is more that one item in the application we need to be able to move between them. As this is an iPad app we want to use a sliding movement to move between records. When moving forwards through the items the old item should slide off the left hand side, when moving backwards the old item should slide off the right hand side.
This effect can be achieved using the command
visual effect push left
The following handler is on the stack script, along with the equivalent moveBack handler. Placing it on the stack script makes it accessible to all the buttons and cards of the stack
on moveForward
## If the current card is not the last card go to the next card
## If the current card is the last card circle to the first card
put the number of this card into tCurrentCard
put the number of cards of this stack into tNumberOfEntries
if tCurrentCard < tNumberOfEntries then
visual effect push left
go to the next card
else if tCurrentCard = tNumberOfEntries then
## Go to the first card
visual effect push left
go to the first card
end if
end moveForward
Using Swipe Gestures
We want to be able to move between records by swiping left or right and moving through the items accordingly. LiveCode provides touchStart, touchEnd and touchMove messages allowing you to detect swipe gestures. By recording the start and end points of the touch and calulating how far the user has swiped, and it what direction you can detect and handle swipe gestures.
These commands are handled on the stack script
on touchStart pID
## When the user touches the screen
put empty into sCoordinateArray["start"]
put empty into sCoordinateArray["end"]
end touchStart
on touchMove pID, x y
if sCoordinateArray["start"] is empty then
put x into sCoordinateArray["start"]
else
put x into sCoordinateArray["end"]
end if
end touchMove
on touchEnd
put sCoordinateArray["start"] into tStart
put sCoordinateArray["end"] into tEnd
## Compare the x coordinates of the start and end point
## This tells us the direction of the movement
if tStart is not empty and tEnd is not empty then
if tStart > tEnd and tStart - tEnd > 100 then
moveForward
else if tStart < tEnd and tEnd-tStart > 100 then
moveBack
end if
end if
put empty into sCoordinateArray["start"]
put empty into sCoordinateArray["end"]
end touchEnd
Testing on the Simulator
At this stage we will try using the iPad simulator to test the app. Save your stack, open the Standalone Application Setting from the File menu and go to the iOS pane.
1. Select build for iOS
2. Select Portrait under User Interface Options
3. Hide the Status Bar
4. Select iPad as the supported device and choose the minimum iOS version
Then click the Test button (5) and the app will be launched in the Simulator
Editing an Item
Editing an item couldn't be simpler. You just click in the field and edit the content.
Deleting an Item
As mentioned earlier we can delete and item by deleting the card that holds its information. Open the script of the "Delete" button and set its script to
on mouseUp
deleteEntry
end mouseUp
The deleteEntry handler goes on the stack script
on deleteEntry
## Delete the current card
visual effect push left
delete this card
end deleteEntry
When a card is deleted the next card is shown automatically. By setting the visual effect first the effect is used to show the next card.
Using a Launcher App
If we just build our application into an iOS standalone it wil work fine but we won't be able to save our data as you cannot save changes to an standalone application. Instead we need to create a launcher application, which in turn launches a version of the Stock Management stack which can be saved.
We save the launcher as standalone and include the Stock Management stack in the application bundle.
iOS imposes strict controls over what you can and cannot access so we use the specialFolderPath function to access the documents folder, this is the folder in which the application should store any document data.
When we first launch the application we copy the Stock Management stack to the documents folder and launch it from there, when saving the stack we save it back into the documents folder. The next time we launch the application we launch it directly from the documents folder as this is the version containing the information.
Saving the Stack
We want to save the stack when the app is closed so that our data is available the next time we start up the app. When the app is closed a shutdown message is sent so we need to add a shutdown handler to our stack script, this uses the save command to save the stack.
on shutDown
## When the app is closed save it to preserve data
save stack "Stock" as (specialFolderPath("documents") & "/Stock.livecode")
end shutDown
Building the Launcher App
To create a launcher stack we create another iPad sized stack, name it Stock Launcher and set the label to Stock Management. This stack shouldn't be seen but we will set the background color to black in case it is seen while the main stack is launching. You can add a "Starting Up" message if you like.
Open the script editor for the stack and add the following handler, this launches the main stack.
on openstack
## The first time the app is started copy the Stock stack
## from the application bundle to the documents folder where it can be saved
## The next time the app is started launch the Stock stack in the documents folder
put specialFolderPath("documents") & "/Stock.livecode" into tMainStackPath
if there is not a file tMainStackPath then
## This is the first time the app has been run
put specialFolderPath("engine") & "/Stock.livecode" into tOriginalStackPath
put url ("binfile:" & tOriginalStackPath) into url ("binfile:" & tMainStackPath)
end if
## Launch the main Stock stack
go stack tMainStackPath
end openstack
We then build the launcher stack into a standalone application(with the same settings as before) including the Stock Management stack as a file.
Testing on the iPad
You can now deploy your app to an iPad and do some testing. Ensure that the gestures work, that you can add, edit and delete stock items and that your data is still there the next time you start up the stack.
Skinning the App
To make the app more attractive you can do some very simple skinning. In this example we have simply used a background image and some button icons. These are all available in the zip file attached to the tutorial.
Import the background image using the Import as Control option in the File menu. Then use the Size and Position pane of the Property Inspector to set the layer of the image to 1, this means it will be below all the controls. You can then move the fields, image area and buttons around to achieve the desired layout.
For a more detailed lesson on customizing the appearance of LiveCode apps please see the Skinning lesson. This goes into detail more detail on using background images, button icons and window shapes.
Darren
I read this How To as I thought it would run through the basics of using a database to store the product data.
I was very surprised to see that a new card is created for each product. Would this result in a large filesize after adding many products?
Would it be possible and better to use SQLite to store the data in a database?
Ben Beaumont
Hi Darren,
Thanks for a very helpful comment. You are absolutely right that if you were to take this application further you may wish to adapt it to store all the data in a database, rather than use multiple cards to store each product. The lesson is designed to help people get into the very basics of creating a simple apps in LiveCode and so does not touch on databases. For those who are interested, please see this lesson:
http://lessons.runrev.com/spaces/lessons/buckets/809/lessons/30516-How-to-create-and-use-an-SQLite-database
I hope this helps.
Warm regards,
Ben
Chris
I am working on a similar app that I want to use on the iPhone.
When the app starts up, the keyboard comes up and covers most of what I want to be viewable.
What would you use in this Stock Control Application to keep the keyboard from appearing
Thanks for any help
Chris
Hanson Schmidt-Cornelius
Hi Chris,
in the property inspector for each field, you could untick the "Focusable" check box on all fields. This will hide the keyboard for you.
Once you get to a point where you would like the user to enter data, you can make the fields focusable again by setting the "traversalOn" property to true for the fields into which you would like the user to enter data.
Use code similar to: set the "traversalOn" of field "XXXX" to true
The field on the highest layer will be focused first, this allows you to control implicitly which field should be focused on first.
Kind Regards,
Hanson
Salman
how can i enhance the swipe code so it can handle an angular swipe for e.g. swiping an object then it launches in a projectile manner. It only stored the x-coordinate of the swipe data how can you store both x and y co-ordinates.
Hanson Schmidt-Cornelius
Hi Salman,
both the x an y coordinates are passed to the "touchMove" message, so you should be able to pick both of the parameters up from there. Have a look at the LiveCode dictionary for more information on this message.
You can convert the cartesian coordinates to polar coordinates, giving you the angle of the swipe.
You may have to adjust the values for each of the quadrants (x,y or x,-y or -x,y or -x,-y). You can find a lot of information on the internet regarding conversion between these two representations.
Kind Regards,
Hanson
Salman
thanks hanson for the info
so far to handle the swipe i have done this
local pX,pY,pX2,pY2
on touchStart flyBall
## When the user touches the image
put empty into sCoordinateArray["start"]
put empty into sCoordinateArray["end"]
end touchStart
on touchMove flyBall,pX,pY,pX2,pY2
if sCoordinateArray["start"] is empty then
put pX into sCoordinateArray["xStart"]
put pY into sCoordinateArryay["yStart"]
put pX and pY into sCoordinateArray["start"]
else if sCoordinateArray["end"] then
put pX2 into sCoordinateArray["xEnd"]
put pY2 into sCoordinateArray["yEnd"]
put pX2 and pY2 into sCoordinateArray["end"]
end if
end touchMove
on touchEnd
put sCoordinateArray["start"] into tStart
put sCoordinateArray["end"] into tEnd
end touchEnd
am i on the right track so far? it comes up as no errors
Hanson Schmidt-Cornelius
Hi Salman,
touchMove only has three parameters, not five. The last two parameters indicate the current x and y position on the touch screen.
I think you could also drop the ["xStart"], ["yStart"], ["xEnd"] and ["yEnd"]. Try using sCoordinateArray["start"] and sCoordinateArray["end"], if you are only trying to find the start and end vectors.
The code:
put pX and pY into sCoordinate["start"]
and
put pX2 and pY2 into sCoordinate["end"]
is a good starting point but you should replace the "and" with "&&". "and" is a logical operator where "&&" is a concatenation operator that inserts a space between its two arguments.
So I would try something like (I have not tested this code):
on touchMove flyBall,pX,pY
if sCoordinateArray["start"] is empty then
put pX && pY into sCoordinateArray["start"]
else
put pX && pY into sCoordinateArray["end"]
end if
end touchMove
Once you reach touchEnd you should get space delimited values in "tStart" and "tEnd".
You may also want to put a condition into the touchEnd event handler to test if sCoordinateArray["start"] and sCoordinateArray["end"] are populated.
Kind Regards,
Hanson
Faisal
Thanks fr a very useful lesson,
I was wondering if there is a way to create a card in desktop and then share it with ios either through iTuens or iCloud or both?
If yes then can you please explain how?
Best.
Faisal
Hanson Schmidt-Cornelius
Hi Faisal,
LiveCode does not have built in connectivity to iTunes or iCloud.
There may be APIs that allow you to connect to these Apple services. Have a look what is available on the internet.
Depending on the possible APIs you may be able to interact with them using the LiveCode "shell" command or you may have to write a LiveCode external that interacts with c/c++ libraries. It really depends on the interface that is provided, if any.
Kind Regards,
Hanson
Geoff Taylor
Wow, the swipe gesture control works brilliantly. And the code so elegant. This really will enhance the user experience in iOS7. Thank you very much!
tyrone Armstead
How would save a picture captured with the mobilphotopick that is put into an image object on a card so when that card is called the picture will appear. I'd like it to save and call the mage to/from the camera roll.
Hanson Schmidt-Cornelius
Hello Tyrone,
you can access files that are local to the application you have written. This means that you can create new files and read them later when the application is opened again. Relevant dictionary entries for this are as follows:
specialFolderPath - Allows you to specify where you would like to read/write to
open file - Allows you to open a file for reading or writing
write to file - Allows you to write to a file
close file - Closes a file
Have a look at these entries for manipulating file data from your application.
Kind Regards,
Hanson