Category Archives: General

VMWare Fusion: Mounting a network drive for reliable cross-platform development with LiveCode


When I’m developing desktop applications in LiveCode I need to test on both macOS and Windows. My primary development platform is macOS and I run Windows using VMWare Fusion. Since I use the Levure framework I can switch over to VMWare at any time, launch a pre-compiled executable, and quickly see how my app behaves. The precompiled executable loads the current development files so I’m testing what I’ve been working on in the LiveCode IDE on macOS.

Up until yesterday there was a problem, however. If I find a bug while testing in Windows I like to switch back to macOS, make the necessary code changes, and then launch the pre-compiled executable to test again in Windows. But sometimes when I launched the executable I would get an error because the source file I just edited (e.g. a .livecodescript file) would be corrupted. For some reason, Windows running under VMWare Fusion was only seeing a truncated version of the file I had just edited. If I opened the file in NotePad I would see that some of the file contents at the end of the file would be missing. The only way to fix the issue was to restart Windows which really slows things down when you are trying to troubleshoot a bug. (Watch a screencast demonstrating my workflow.)

The interesting thing is that this had not always been a problem. In the past I had used the same workflow with VMWare Fusion and had no problems.

Yesterday I upgraded to VMWare Fusion 10 hoping that the problem might be fixed. When I saw that it wasn’t I decided to email VMWare support to see if they knew what was going on. I was pleasantly surprised to get a call back from their technical support team in no time at all. We got on a screen sharing session, I showed them what was going on, a knowledgable person then got on the phone with me and talked me through the solution which I will describe below.

Don’t use Shared Folders for development work

At some point I had set up VMWare Fusion to use Shared Folders. This is an easy way of making folders on macOS available to Windows. While it is convenient, the feature wasn’t designed to be used the way I’m using it for development work and the issue I described above can occur.

Mount a network drive

The solution is to mount your macOS folder as a network drive. This involves a little more work but is simple enough if you know what to do. I’m going to show you how to create a private network between VMWare and your Mac so that you don’t have to worry about which network you are on.

Add Device…

  1. To begin, turn off your VM and open the settings.
  2. Click on the Add Device… button.

Add a Network Adaptor

Select Private to my Mac

  1. Click on the Private to my Mac option
  2. Click Show All

You should now see two network adaptors in the Settings window.

Turn on File Sharing on your Mac

  1. Navigate to the System Preferences > Sharing panel and turn on File Sharing.
  2. Make note of the smb address.
  3. Click on the Options… button.

Turn on SMB file sharing for your account

In order to mount your folder as a network drive in VMWare you will need to check the box next to the account you want to share.

Map network drive

You are now ready to launch Windows in VMWare Fusion and map a network drive.

  1. Select This PC in the left column of a Windows Explorer window.
  2. Click on Map network drive and select Map network drive.

Enter the path to your macOS user folder

Using the smb address you noted earlier, enter the path to your user folder on macOS. In this example I used the following:


Enter your macOS login and password


Your macOS folder will now appear as a networked drive under Windows. You can drag any folders from the networked drive to the Quick Access area so that you can quickly navigate to the applications you want to test. Using this approach you can edit files in macOS and know that the file contents will be updated properly within Windows running in VMWare Fusion. Happy testing!


Exporting SVG files from Adobe Illustrator for use with drawingSvgCompileFile()

In LiveCode 9 the image object has been updated with support for resolution independent vector data. In addition, a new Drawing Library is included which has two functions that will convert an SVG file or SVG data to a format that can be assigned to the text of an image. The end result is that developers can now import SVG files into the LiveCode image object. This is a great way to include resolution independent graphics in LiveCode applications.

Given that LiveCode 9.0 does not support the entire SVG specification it is possible to create SVG files that will not import into LiveCode properly. This article will show you how to export an SVG file from Adobe Illustrator that will display properly in LiveCode.

Continue reading


RunRevLive 09 Resources

I took down the original page of links to my session materials that  I posted for the RunRevLive 09 conference so I’m reposting the content here.

Behaviors and Custom Controls

Behavior Helper Plugin

Custom Control Helper Plugin

Behaviors & Custom Controls Stacks

Instructions Showing How To Install a Plugin

Password Font

Presenting Data with the Data Grid

Data Grid Sample MP3 Library

Creating a Music Library Interface Part I


Displaying Placeholder Text In a Field

Have you ever wanted to display the grey text that describes what a text field does?

Placeholder Text Example

Google search field in Safari

Placeholder text can be very useful as it provides a visual queue to the user about what the field does while not requiring any extra space in your UI.

Using custom properties and behaviors (new in Revolution 3.5) you can easily add this feature to fields in your applications. See the lesson How To Create Field Placeholder Text Using Behaviors.


Libraries & Error Reporting

Lately I’ve been working with a lot of web services in ScreenSteps. ScreenSteps integrates with services like WordPress, TypePad, Confluence, MindTouch and ScreenSteps Live. When I sat down to write libraries for each of these integrations I wrestled with how I wanted to handle error reporting. Each handler that retrieved data from a web service would return data that I needed to process. At the same time, I also needed to know if something went wrong while communicating with the web service.

I considered 4 possible approaches.

1) Handlers That Return Valid Data or Errors

If you have ever used one of the Revolution externals such as revDB or revXML then you are familiar with this technique. The handlers in these externals can return valid data or a string that starts with revdberr, or revxmlerr,. This is what a WordPress library handler might look like using this method:

put wp_getCategories(pParamsA) into theData
if theData begins with "wperr," then
   // item 2 to -1 of theData contains an error
   // theData contains valid data
end if

2) Function That Returns Last Error Generated By Library

When working with libraries another option is to have the library log any errors internally and then have a function that returns the last error generated by the library. This is what a WordPress library handler might look like using this method:

put wp_getCategories(pParamsA) into theData
put wp_lastError() into theError
if theError is not empty then
   // Something bad happened
   // Do something with theData
end if

3) Throw Errors
Another option is to throw any errors that occur within one of the library handlers. This requires wrapping any calls to the library handlers in try/catch statements.

   put wp_getCategories(pParamsA) into theData
catch theError
end try

if theError is not empty then
   // Something bad happened
   // theData contains valid data
end if

4) Place Errors in the result and Return Data In it

This is the approach that the Revolution engine uses in many cases. For example, if you use the post command any errors are reported in the result and the data returned from the web server is placed in the it variable. Likewise, this is how a command like decrypt behaves. This is what a WordPress library handler might look like using this method:

wp_getCategories pParamsA
put the result into theError

if theError is empty then
   // 'it' contains data returned from the server
   // Something bad happened
end if

I’ve never liked option (1) as I don’t think that mixing error reporting and results is a good idea. What if the actual value started with your error string? Likely? No. Possible? Yes.

Option (2) would probably work fine as I don’t think you would get invalid results if you had multiple calls to the library going on with send in time calls (I could be wrong but I didn’t go with this approach so I didn’t test it). I just don’t care for that sort of API.

Option (3) requires too many lines of extra code for my taste and it doesn’t seem appropriate to throw an error if communication with the web server fails for some reason. Throwing errors should be reserved for circumstances where the developer has passed in bad data that he should have cleansed ahead of time.

That left me with option (4) and this is the option I ended up using. The reason I like option (4) is that this is how the engine behaves in a number of places. Errors and data are clearly separated and I like using a “native” approach as calls to my library handlers will read the same as calls to engine handlers.

There was only one problem left. How could I set the it variable in a command? Revolution only supports setting the result from a command. It turns out that you can set variables in calling handlers by using the debugContext so I whipped up a little handler called SetValueOfItInCaller that did just what I needed. Take a look at the Write a Command That Sets ‘the result’ And ‘it’ lesson to see the solution.


Loading Stack Files Into Memory

In my applications I like to verify that all stack files exist on disk when the application launches. If any of the required stack files are missing then I alert the user and quit the application.

Most developers are familiar with using

go [invisible] stack "/path/to/stack"

to load a stack file into memory. But ‘go stack’ actually opens the stack on screen and triggers the [pre]openStack and [pre]openCard messages. You don’t want either to happen if you are just validating stack file existence and loading into memory. Although you can hide the stack and lock messages there is a way that requires less lines of code.

The best way to verify that a stack file exists on disk and load it into memory without triggering any messages or showing it on screen is to do this:

put there is a stack "/path/to/stack" into theStackFileIsLoaded

By checking for the existence of the stack file on disk, Revolution will load the stack into memory. if theStackFileIsLoaded = false then you know the stack file doesn’t exist.

On a somewhat related note check out the Knowing Which Stacks Are In Memory lesson. It has a function that lists all stacks that are currently loaded in memory.


Data Grid Webinar

A few weeks ago Kevin Miller, Bill Marriott (both of Runtime Revolution) and I put on a webinar that introduced the new Data Grid in Revolution 3.5. The data grid was originally developed for ScreenSteps so that we could provide our customers with a much more responsive UI when working with large libraries and lessons. We were thrilled when Revolution decided to integrate it into their core product.

Given the extremely positive response by attendees, Greg and I thought people might be interested in seeing how ScreenSteps 2.5 uses data grids throughout the application. So we’ve added a new webinar to our webinars page entitled Using Data Grids in Revolution 3.5. In the webinar we will show you:

  • The various UI elements created using the data grid.
  • The techniques used to create some of the visuals.
  • The techniques used to hook the data grids up to data from SQLite, stacks, folder contents and the web.

We also plan on providing ample time to answer questions people might have. So join us on Thursday April 30th if you want to improve your data grid chops.

Sign up for webinar

Update: The webinar video has been posted in our archive.