Wednesday, September 26, 2012

Guest Blog Post: Real Studio App Saves Millions of Dollars for Investment Company


Kuwait & Middle East Financial Investment Company is a stock brokerage company operating out of Kuwait. Each year, our company would pay millions of dollars to various software companies and vendors for licenses, maintenance fees and occasional feature requests for our various internal and stock trading applications. 

As an experienced Real Studio programmer, I saw an opportunity to save the company millions of dollars by using Real Studio to build these applications internally. I convinced Kuwait & Middle East Financial Investment Company to buy Real Studio and third party plugins from Monkeybread Software and Einhugur. 

Within 7 months, I had developed both a beautiful stock trading and an internal office application which suited our needs. Each time I come across a question about a feature, I found an answer from the Real Studio community on the user forums. All our applications are based on client-server architecture. The server side components are in Linux servers and client side is based on Windows. 

Our new, Real Studio built, stock trading application allows for live trading in the stock market using FIX 5.0 protocol standards and displays a live market feed. 





The internal office application is used for order management and features buying power to avoid short selling, automatic sending reports via email and fax to clients after end of market in PDF format, automatic generation of vouchers in general ledger when trades a occurs, as well as all required features for a stock brokerage firm.






Our company is very satisfied by this move and couldn’t have saved this much money without Real Studio.

Sunil S Abraham is the Senior System Developer, IT - Run Division for Kuwait & Middle East Financial Investment Company. Originally programming in VB 6, Sunil started searching for an alternative in 2004. Once he discovered Real Studio he "never looked back" and has been actively developing in Real Studio since 2005, porting multiple VB 6 applications over the years.

Monday, September 24, 2012

Uniform Type Identifiers on OS X


Before OS X 10.4, OS X used File Types and Creator Codes to identify documents created by applications.  Since then Apple has been phasing out Creator Codes and File Types.  It now recommends that you use a Uniform Type Identifier (UTI) to identify documents.

A UTI is a special text string that identifies both data and application documents.  For example, the UTI for a PNG picture is public.PNG.

You would use the same UTI for a PNG file.

If you are working with common file types, you should use the public UTI for it.

Here are some links for reference:
Note: UTIs work with both Cocoa and Carbon applications.

Custom UTI

For your own documents, you can create your own UTI.  A custom UTI typically has a “reverse-domain name” format plus an additional entry for the document type name.  So you might have a UTI such as “com.company.app.doc”.  The first part of this UTI must match the Application Identifier specified in the App properties (com.company.app in this case).

You create a UTI for your documents using the File Type editor.  The last column in the editor lets you specify the UTI.

When you build your application, the UTI information is included in the Info.plist file in the application bundle.  But in order for this to work properly, you have to add an additional “UTExportedTypeDeclaration” section to the plist manually.

Setting up a Custom UTI

These are the steps to create a custom document type that can be opened by your application. You need to do these steps after each build of your application because the Info.plist that you need to modify is recreated with each build:
  1. In the App Properties, set these values:
    • Specify the application identifier for your application using reverse domain name format: com.company.app
    • Enter “????” as the MacCreator. This is simply a placeholder; it is not used.
  2. Add a File Types Set to your project.
    • Enter a name for Display Name and Object Name (such as MyCustomDocType).
    • Enter “????” for MacType and MacCreator. These are placeholders and are not used.
    • Specify your extension (without a period).
    • Enter the UTI using your application identifier as the base.  For example, this could be your doc UTI: com.company.app.doc
    • Choose the icon to use to identify files of this type.
  3. Go back to the App Properties and set this value:
    • Specify your File Type in AcceptFileTypes
  4. Build your application.
  5. In Finder, go to your application and select “Show Package Contents” from the contextual menu.  Navigate to the Contents folder and open Info.plist file in a text editor.  Add the following code to the end (before </dict>), replacing the UTI (com.company.app.doc) and extension (myextension) as appropriate:
    • <key>UTExportedTypeDeclarations</key>
        <array>
          <dict>
            <key>UTTypeConformsTo</key>
            <array>
              <string>public.data</string>
              <string>public.item</string>
            </array>
            <key>UTTypeIdentifier</key>
            <string>com.company.app.doc</string>
            <key>UTTypeTagSpecification</key>
            <dict>
              <key>
      public.filename-extension</key>
              <array>
                <string>
      myextension</string>
              </array>
            </dict>
          </dict>
        </array>
  6. Save Info.plist
  7. Navigate back to the your application in the Finder and Run your application to register the types
When you use GetSaveFolderItem (or SaveAsDialog), you supply the FileType to use as the Filter.  A custom document created with the selected file will be associated with your application so that the specified icon appears and so it can be opened by your application.

Dim f As Folderitem
f = GetSaveFolderItem(FileTypes1.CustomType, "Untitled" + FileTypes1.CustomType.Extensions)

If f <> Nil Then
  Dim output As BinaryStream
  output = BinaryStream.Create(f, True)
  output.Write("CustomType: Sample Text")
  output.Close
End If

When you view the saved document in the Finder, you will see that it has the specified icon.  Double-clicking it will launch your app (if it is not already launched) and call the OpenFile event.

Opening files works by supplying the name of your FileType as the filter of an open dialog:

Dim f As FolderItem
f = GetOpenFolderItem(FileTypes1.MyType)


Migrating to UTIs from MacCreator and MacType

If you have been using the MacCreator and MacType properties of a FolderItem and specifying them in File Type Sets, then you need to start using UTIs soon.  Apple has deprecated both MacCreator and MacType.

To switch to using UTIs, you simply need to start using UTIs in your File Type Sets and updating Info.plist as described earlier.  You can leave the old MacCreator and MacType setting in place or you can remove them so that you do not get deprecation warnings when analyzing your projects.

Monday, September 17, 2012

Creating Web Dialog Boxes On-The-Fly Redux

As previously mentioned by Geoff in his post "Creating Web Dialog Boxes On-The-Fly", Real Studio web edition works a little differently than the desktop in how you set up a dialog for use.

It's handy to be able to drag an instance onto a window  and deal with its events and everything the same as any other control.

But, as Geoff noted there are times when you don't want to do it that way because you need to reset the dialog to a default state.

You might want to have a different dialog based on what browser is being used or other criteria. In such cases, you might want to use a dialog superclass and have several different implementations that vary in appearance for iOS, Android, or for different browsers.

This is easily possible using the same technique Geoff illustrated for dynamically creating a dialog.

For example, suppose you need a dialog that looks one way for Safari and another one for all other browsers- we could just as easily extend this to Firefox or make it appear different for iOS vs Android.

Instead of dragging one of each dialog onto your layout, you could have both derive from a common superclass. With only 1 or 2 variations it's easy to drag them all out, but if you need many more that could be tedious and makes adding a new one more difficult than it needs to be, and you'll end up having a lot events to handle.

If you have a common parent with subclasses your code can do:

dim theDialog As GenericMobileDialog // this is defined as the common parent class type
if plat = WebSession.BrowserType.Safari or plat = WebSession.BrowserType.SafariMobile then
theDialog = new SafariVersionOfDialog
else
theDialog = new NotSafariVersionOfDialog
end if
AddHandler theDialog.Dismissed, AddressOf LogInDismissed
theDialog.Show

And now you can set up as many as you want AND handle them all with a very few lines of code.

A sample project that demonstrates this can be found here.

Wednesday, September 12, 2012

Tips for Working with VCP projects & SVN

Now, before everyone gets all agog, I'm NOT an SVN expert BUT I am quite familiar with how to use it in conjunction with Real Studio & VCP files.

Most of this experience comes from having worked for Real Software for the last 4 years and dealing with SVN on OS X, Windows & Linux. We use all three here and there are a very minor number of issues that we run into. If you have a team also using SVN then you're likely to experience them as well.

First things first - use VCP with SVN :)

Yes, you can use XML, but XML files are much harder to merge and compare differences because they are XML. We do use some binary files, mostly images, and there's not a lot you can do to practically compare two binary files. It would be nice, but SVN doesn't do that. Now IF you happen to use a LOT of external files, which has pros and cons in a team environment especially if you're doing work for many clients, you may have to use either XML or RBP files. There's no way around that at the moment. That's one of the issues with external items.

The other issue is that if you use some common code you might be better off being able to "clone" it to client projects on a predictable schedule that you control, instead of just whenever it's updated in another project. And SVN does make this possible if you use subprojects or relative locations. (see http://tortoisesvn.net/docs/nightly/TortoiseSVN_en/tsvn-howto-common-projects.html) This allows you to keep your "common code" up to date in one place and then YOU decide when to update it to other projects you use it in.

With SVN in a team environment one of the things you definitely want to avoid is nuking another developer's changes. As long as you regularly update from the repository, this is not hard to avoid and most are easy to deal with. And always update BEFORE committing your changes just to make sure you're not about to put some code back in your main repository that has conflicts. Conflicts arise when you and another team member happen to change the same line in a file. When you update, most SVN clients will highlight the difficulty and let you know. When it's in code, it's not a problem and the IDE will open the items and you can find conflicts by running an analyze, and the IDE will highlight the conflict markup as invalid syntax.

The hardest conflict to deal with is when you add something to the project and someone else does as well in their working copy. In a VCP project, adding an item modifies the "manifest", the file with the RBVCP extension, that represents the items in your project. A conflict in this file will make it so your project won't open any more as the IDE has no clue what this conflict markup code means.

So what does a conflict look like and better yet, how do you fix it ?

The first thing to know is the RBVCP file is just a text file so you can open it with TextEdit, NotePad or any other text file editor (emacs, vi, vim, or pico for those who are so inclined).
Often a conflict will look like:



<<<<<<< .mine 
Folder=Autocomp Stuff;Autocomp Stuff;&hBC57A158;&h0;false 
======= 
Folder=RB Language Support;RB Language Support;&hBC57A148;&h0;false
>>>>>>> .r6
which says that in MY local copy of the RBVCP file I added a Folder (hence the Folder=) and that in the repository that line has a different folder - someone else added that and checked their change in before mine.

In this case I want to keep both things, otherwise I'd drop the other person's new folder from the project. You'd edit the RBVCP file and make sure both lines are in the file. Then mark the conflict as "resolved" - how you do this varies from SVN client to SVN client - and commit that change.

Changing Your Debug Build Location


Recently, we were contacted by a teacher who uses Real Studio in her classroom. Her students log into their computers with their network login IDs and connect to a student server where they save their work to a folder. However, her students found that after they ran their apps once, they were unable to do so again because the Application.Debug file that is created in their folder is continually in an opened state until the student logs out.

Normally when you run a project, it is created in the same folder as the project itself, which was the cause of this problem.  This usually makes the most sense, but there are times when it makes sense to instead build your app elsewhere.

These are some additional reasons you might want to have this debug application in a different location:
  • You keep your source code on Dropbox and don't want to have the debug builds automatically sync
  • You don't want the debug builds cluttering up your source control folder
  • You want to use a high-speed SSD for the debug build so that your projects build and launch faster
  • Your projects reside on a shared network drive causing debug builds to be slow or files to remain locked
So how do you change the debug build location?  It's actually pretty easy.  You use the Destination property of the App class.  This property is located in the Debugger section at the bottom of the Preference pane.


Destination Property of App Class

To choose an alternate path, click the "..." button on the right to get a Select Folder dialog.  Choose the folder to use and click OK.

The next time you run your project, the debug application will be built in this location instead of alongside the project.  Simply clear the property to have the builds again happen in the same folder as the project.

Monday, September 10, 2012

Creating Web Dialog Boxes On-The-Fly

When creating a web application with Real Studio, dialog boxes can be managed in a way that is much easier and nicer than in a desktop application. After creating the dialog box, you can just drag it onto the web page in which you wish to show the dialog. An instance of the dialog appears in the tray at the bottom of the layout editor:



To display the dialog box, simply call the Show method from the instance you added. For example,  to show the dialog above, your code would be:

MyLogin.Show

To help you visualize it, here's the example login dialog box in action:



What makes web dialog boxes different from how dialogs are handled in desktop applications is that in web applications the dialog as a whole is treated like a control. It has events and maintains its values while the web page is open. For example, if the user clicks a checkbox in the dialog or fills in a textfield, when you display the dialog again, those values will still be set. This can be convenient if that's the behavior you want. If it's not, it might be your instinct to add code to the Shown event (either of the dialog or the individual controls in the dialog) to reset things. Perhaps you need to set a checkbox back to unchecked (or checked) or clear the values from textfields.

Rather than writing all that code that then has to be maintained, you can instead create an instance of the dialog on-the-fly rather than dragging it to the page itself to create an instance. The advantage is that since you are creating it on-the-fly each time its going to be displayed, the controls will automatically be reset to their default values.

To display the dialog is easy enough. You create an instance of the dialog then call the Show method:

dim theDialog As New LoginDialog
theDialog.Show

The example above is a login dialog box. Where would you put the code to log the user into your system? Ideally, you would keep that code with the web page that displays the dialog since you might use this dialog for another purpose on another page. It's easy to display a web dialog using the method first described, simply put your code in the Dismissed event of the web dialog instance on the page. That's the MyLogin web dialog box in the first figure above. You might think that when creating a web dialog on-the-fly, you would simply add your code after calling the Show method. For example:

dim theDialog As New LoginDialog
theDialog.Show
'code to log into the system goes here

That won't work because web dialogs, even when instantiated on-the-fly, execute asynchronously. That means that while the dialog will be displayed, the code following the Show method won't wait for the dialog to be dismissed by the user. It will execute immediately. So that method is not going to work.

You might be thinking you will just use the web dialog's Dismissed event. The problem with that solution is that this event is part of the web dialog itself and not part of the page where the dialog is used. That means that you can't easily use the web dialog with different pages.

The solution is to re-route the web dialog's Dismissed event so that it causes a method of the web page itself to execute. The code that should execute when the dialog is dismissed will be part of the web page that called an instance of the web dialog in the first place. To do this, you use a method call AddHandler. Using this method, you are telling the web framework that you want to delegate responsibility for handling a particular event to a method instead. AddHandler needs to know which event you want to delegate and the method that will handle the event. Here's a version that uses the AddHandler method when displaying the same dialog box:

dim theDialog As New LoginDialog
AddHandler theDialog.Dismissed, AddressOf LogInDismissed
theDialog.Show

LoginDismissed, in this case, is a method of the web page that is displaying the dialog box. The AddressOf operator is passing the memory address of the LoginDismissed method so that it can be executed when the Dismissed event fires. That's it. Just add a LoginDismissed method to the web page and write the code there that should execute when the dialog is closed. When you want to use this dialog with another page, just add a LoginDismissed method to that page and use the same code above to display the dialog box. The LoginDismissed method will be passed a reference to the dialog object so you can easily access the dialog's various controls.

In this example, the Login dialog has Cancel and OK buttons. You need to know which one they clicked. So the LoginDialog has an Accepted As Boolean property. The Action event of the OK button sets this property to true so you just test for that in the LogInDismissed method:

LoginDismisssed(theDialog As LoginDialog)
  if thedialog.Accepted then
    MsgBox "The user clicked OK."
  end if
End Sub

Creating a web dialog on-the-fly is a little more work than simply dragging one on to a web page, but it also can save you from having to write extra code to reset the dialog each time you display it should you need that behavior.

There's an example project available here.

Thursday, September 6, 2012

Real Studio iOS Update: Graphics

At our Real World conference last May I showed a sneak peek of the work we are doing to support iOS in Real Studio. At that time, we had only implemented a few controls, really just enough to be able to give a demonstration. 

Now we are working on support for graphics. As you can see in the screenshot below, we have the canvas control working with the basics of the graphics class.

The order in which we are developing is designed to determine any major issues as early in the process as possible. Controls are very straightforward so we are not spending a lot of time on those right now. We'll post more updates as development continues.

Wednesday, September 5, 2012

Dealing with Flickering on Windows

I am often asked if we have solved the flickering problem that is often seen on Windows applications. Unfortunately, this is mostly an issue with Windows itself. Unlike OS X and Linux, Windows does not double-buffer window updates. This is a source for annoying flicker in a wide variety of Windows applications, including those made with Real Studio.

However, there are strategies you can use to minimize flickering in your Windows applications.


Do Not Overlap Controls

The easiest thing you can do to prevent flickering is to not overlap any controls.  Overlapped controls result in more requests to redraw the controls which results in flickering.

Use a Canvas

For best results, display your graphics using the Paint event of a Canvas control.  Stay away from using the Window Paint event, the Canvas.Backdrop property or the ImageWell control.  Although those techniques work fine in certain situations, they often lead to flickering in more complex window layouts.

On the Canvas, the first thing you want to do is enable the DoubleBuffer property and disable the EraseBackground property.  The DoubleBuffer property allows the Canvas to do its updates offscreen to minimize flicker.  The EraseBackground property prevents the Canvas from being erased (and showing as a white rectangle) before it is redrawn, which is a common source of flicker.  Now you can do all your drawing in the Paint event using the supplied graphics object, g.

Note: Do not do any drawing directly to the Canvas.Graphics property. This will likely increase flickering and will definitely slow down graphics updates.

You can have separate methods that update the graphics, but they need to be called from the Paint event with the graphics object supplied to the methods as a parameter.
When you want to update the graphics in the Canvas, you call the Invalidate method:

Canvas1.Invalidate

You can also call the Refresh method:

Canvas1.Refresh

The difference is that Invalidate tells the Canvas to update itself when it gets a redraw request from the operating system.  The Refresh method tells the Canvas to update itself immediately.  Generally, Invalidate is more efficient and should be your first choice.

Both of the above commands do not include the EraseBackground parameter, so it defaults to True. This means that the Canvas is erased before the contents are redrawn, which can result in flicker.  Instead, you should draw the background yourself and disable EraseBackground by passing False instead.

Some Tricks to Make this Easier

In general, you do not want to use EraseBackground at all.  Anywhere that it is specified or used, you should always set it to False (this incudes Canvas, canvas methods and ContainerControl)

One trick you can use to make this easier is to override the Refresh and Invalidate methods to ignore the EraseBackground flag.  For example:

Sub Invalidate(EraseBackground As Boolean = True)
 Super.Invalidate(False)
End Sub

As mentioned above, you also do not want to access Graphics directly.  In order to catch situations where you might do this accidentally, you can add a Graphics method that returns Nil.  This way if you mistakenly call Canvas.Graphics, you will get a NilObjectException:

Function Graphics() As Graphics
 Return Nil
End Function

If you are creating a cross-platform application, Canvas.DoubleBuffer is not needed on OS X or Linux.  For maximum performance, you should disable it on those platforms using conditional compilation:

#If TargetWin32 Then
  Me.DoubleBuffer = True
#Else
  Me.DoubleBuffer = False
#Endif

I hope these tips help you to create great-looking Windows applications in Real Studio.

Update Your Plugins for Real Studio 2012r1

Real Studio 2012 Release 1 makes use of the updated plugins API.  In addition, some older classes that have been deprecated for a while have been removed (such as ContextualMenu).

This means, more so than past releases, you also need to make sure you are have installed the latest versions of any plugins that you use.

Older plugins that may still be relying on no longer supported API calls or removed functionality.  This could cause them to behave unreliably and possibly cause instability when used with 2012r1.

For your reference, here are links to popular plugins used with Real Studio:

MonkeyBread Software
Einhugur
Van Hoek
Bob Delaney