A client needed their sales staff to be able to print to a mini bluetooth printer from a LiveCode iOS app. The solution was to create another external for the mergExt suite called mergAccessory. With this new external you can connect to, write to and read from accessory hardware that are part of the Made for iPhone program. I’ve included in the download an example for printing to my client’s chosen accessory the BlueBamboo p25i.
The first in my series of articles demonstrating the creation of an iOS app using a number of mergExt externals and MobGUI has been published. To celebrate the release there’s half price off mergExt and MobGUI when bought together from the RunRev Marketplace and using the coupon code MERGUI.
The mergZXing project has evolved into a suite of externals for LiveCode. The externals are currently only for LiveCode iOS but long term plans involve all platforms. The suite is called mergExt (standing for M E R Goulding EXTernals) and is available at http://mergext.com. Development of new externals is driven by a community ideas forum and a poll to indicate what people need the most.
Today I announced a demo for my barcode reader external called ShakeNScan is available in the app store. Sorry about the app, I built it in about an hour as it’s sole purpose is to demo the modal barcode reader, ensure the external was not a blocker for app store release (which obviously I now know it’s not) and to gauge interest in it. I’m keen to hear if you have a need for it.
The external can read EAN-13/UPC-A, UPC-E, EAN-8, Code 128, Code 39 and QR Code. The app will browse to a url in a QR code but it will display the results of all the other codes. It uses one function mergGetBarcode() which presents a modal barcode reader using the back camera. An embedded barcode reader control is in the works but there’s still some issues with that I’m working through.
http://itunes.apple.com/us/app/shakenscan/id490000309
It will be available via revSelect as soon as I can arrange it.
EDIT
This external along with a heap of other externals for iOS are available at mergExt
I spent an hour this afternoon having a play with the AppleScript commands for Growl and came up with a this little plugin toy for LiveCode. It notifies you when LiveCode is saving a standalone and when the standalone is saved. If anyone can think of anything else they might like notifications of I’m happy to add some more but this is really just a demo of the growl library which is a substack of the plugin.
| Download: Growl for LiveCode 1.0 (3.02 kB) Description: Growl plugin and library for LiveCode |
This week I had a report of an application locking up while executing the shell function. Actually it was executing shell(“ipconfig /all”) in my modification of Ken Ray’s GetMACAddress function to return the machine’s LAN ip.
System administrators tend to like to turn things off so normal human beings can’t make a mess of their nice machines. One thing they can do is set a Windows registry entry to disable cmd.exe for the user. So by checking HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\DisableCMD”=dword:1 we can find out if cmd.exe is disabled for the current user. What this does is when cmd.exe is run it opens the console but all you get is a blocked by admin message and no command prompt. If Bill would just change this so it stopped cmd.exe from launching at all then we wouldn’t have such a problem. LiveCode is therefore able to run cmd.exe and just sits there waiting for it to terminate but it never does.
So I wrote a safer shell function to check for this situation and also possible execution errors from hash rules and renaming of cmd.exe etc. If the registry setting is there it will attempt to execute the command directly using process commands rather than via shell.
function safeShell pCommand -- assume the shellCommand has been set appropriately set the hideConsoleWindows to true set the itemDel to "\" if item -1 of the shellCommand is "cmd.exe" AND \ charToNum(queryRegistry("HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\DisableCMD")) = 1 then -- don't use cmd.exe because shell() won't return -- don't revert to command.com because there seems to be a problem in the engine return executeProcess(pCommand) else try -- still check for empty if your are expecting a result -- because there's no execution error on os x return shell(pCommand) catch e -- execution error on windows shellCommand doesn't exist -- hopefully this catches hash rule blocks return "Error executing command" end try end if end safeShell function executeProcess pProcess,pElevate local tReturn if pElevate then open elevated process pProcess for text read else open process pProcess for text read end if repeat forever # Loop until there are no more lines to read. read from process pProcess for 1 line if the result = "" or the result = "timed out" then -- something to add put it after tReturn else close process pProcess return tReturn end if end repeat end executeProcess
I have a project where using a data grid form really simplifies things, however, it’s critical that the user can re-order the list in arbitrary way. To do this I needed to add drag and drop to the data grid.
First I wrote rolled my own:
There two main limitations with this code are that it will only work for a data grid form (not table) and only if the cache controls property is true.
local sDragImage,sControlIndexMap,sOriginalIndexes on dragStart local tControl,tItem set the dragData["private"] to "dgDragIndex"&&the dgHilitedIndex of me put the dgDataControlOfIndex[the dgHilitedIndex of me] of me into tControl lock screen import snapshot from tControl put the long id of the last image into sDragImage set the visible of sDragImage to false set the dragImage to the short id of sDragImage put the dgIndexes of me into sOriginalIndexes delete variable sControlIndexMap repeat for each item tItem in the dgIndexes of me put tItem into sControlIndexMap[the dgDataControlOfIndex[tItem] of me] end repeat set the allowableDragActions to "move" pass dragStart end dragStart on dragMove pX,pY local tDragIndex,tNewIndexes,tOverIndex if word 1 of the dragData["private"] = "dgDragIndex" then unlock screen lock cursor -- refresh bug workaround on setting the dgIndexes the dragAction seems to get set to none put word 2 of the dragData["private"] into tDragIndex set the dragAction to "move" if pY > the bottom of me-20 then if item 2 of the dgVisibleLines of me < the dgNumberOfLines of me or the scroll of me is not the dgFormattedHeight of me then set the dgVscroll of me to min(the dgVscroll of me + 20, the dgFormattedHeight of me) end if else if pY < the top of me+20 then if item 1 of the dgVisibleLines of me > 1 or the scroll of me is not 0 then set the dgVscroll of me to max(the dgVscroll of me - 20,0) end if end if repeat with X=1 to the number of groups of group "dgList" of me if the visible of group X of group "dgList" and the short name of the owner of group X of group "dgList" is "dgList" then if (pY >= the top of group X of group "dgList" of me) and (pY < (the top of group X of group "dgList" of me+(the bottom of group X of group "dgList" of me-the top of group X of group "dgList" of me) div 2)) then -- place above index put sControlIndexMap[the long id of group X of group "dgList" of me] into tOverIndex --put "over"&&tOverIndex if tDragIndex = tOverIndex then put sOriginalIndexes into tNewIndexes else put sOriginalIndexes into tNewIndexes delete item itemOffset(tDragIndex,tNewIndexes) of tNewIndexes put tDragIndex&"," before item itemOffset(tOverIndex,tNewIndexes) of tNewIndexes end if set the dgIndexes of me to tNewIndexes put tNewIndexes into sOriginalIndexes else if (pY <= the bottom of group X of group "dgList" of me) and (pY > (the top of group X of group "dgList" of me+(the bottom of group X of group "dgList" of me-the top of group X of group "dgList" of me) div 2)) then -- place below index put sControlIndexMap[the long id of group X of group "dgList" of me] into tOverIndex --put "over"&&tOverIndex if tDragIndex = tOverIndex then put sOriginalIndexes into tNewIndexes else put sOriginalIndexes into tNewIndexes delete item itemOffset(tDragIndex,tNewIndexes) of tNewIndexes put ","&tDragIndex after item itemOffset(tOverIndex,tNewIndexes) of tNewIndexes end if set the dgIndexes of me to tNewIndexes put tNewIndexes into sOriginalIndexes end if end if end repeat end if pass dragMove end dragMove on dragEnd -- clean up if sDragImage <> "" then delete sDragImage put "" into sDragImage end if pass dragEnd end dragEnd
Then I had a poke around the data grid behavior script and found undocumented support for drag and drop. So here’s the new script that does not have the limitations of the above and is obviously far less verbose:
on dragStart local tIndex if (the dgHeader of the target is empty) then put the dgIndex of the dgDataControl of the target into tIndex set the dgDragImageIndex of me to tIndex set the dragData["private"] to empty set the dgTrackDragReorder[tIndex] of me to true end if end dragStart on DragReorderDrop pOriginatingIndex, pStartLine, pDroppedOnLine if (pStartLine is not pDroppedOnLine) then SetLineOfIndex pOriginatingIndex, pDroppedOnLine send "RefreshList" to me in 0 secs end if end DragReorderDrop on dragMove set the dragaction to "move" end dragMove
For the past few weeks I’ve been playing with the revIgniter Web Application Framework whenever I get a chance. It’s a very impressive piece of work written by Ralf Bitter as a LiveCode Server implementation of the PHP CodeIgniter framework.
One of the first things I was keen top implement is a Facebook API library. The starting point is the Open Graph Protocol that defines page metadata to give pages context. The Open Graph Protocol is what allows Facebook to show a nice title, image and description etc when you paste in a link.
If you are interested in the library or want to contribute to it and the facebook library coming next then check out the repo at github:
http://github.com/montegoulding/revIgniter-open-graph
This new version of revObjective separates out the startup code from the main plugin along with a couple of minor user interface changes.
| Download: revObjective 1.2 (56.13 kB) Description: A behavior scripts and custom object manager. To install just unzip the file and copy the contents into your user plugins directory. |
A screencast showing the basics of working with revObjective is included below.
A new behavior script and custom control manager plugin for Revolution.
Features include:
- Adds an object placing menu button to the tools palette for both revObjective and standard Revolution object libraries.
- Add, Delete, Clone, Place, Edit Script, Edit Controls, Name, Describe, Author, Version your custom controls.
- Drag and drop objects onto your stacks from the object list.
- Drag and drop revObjective files to and from the object list to share.
- Searches stacks during standalone building and finds revObjective behaviors and copies over the behavior scripts in a way that is not file path dependant.
- Packaged with revObjective are MacOS X Search Field, Integer Field, Decimal Number Field and Placeholder Text Field
| Download: revObjective 1.2 (56.13 kB) Description: A behavior scripts and custom object manager. To install just unzip the file and copy the contents into your user plugins directory. |
This plugin is donationware. If you decide it fits into your workflow then please consider donating to encourage further development.

