Tuesday, December 11, 2012

Resources in Managed C++

I was trying to write an MSBuild file for a managed C++ project, using Windows SDK 7.1 (and not Visual Studio). Mostly the supplied .targets/.props files do the hard work for you (the documentation seems rather sketchy AFAICS.) One stumbling block was the resources, I kept getting an error:
System.Resources.MissingManifestResourceException: Could not find any resources appropriate for the specified culture or the neutral culture.  Make sure "controller.Form1.resources" was correctly embedded or linked into assembly "controller" at compile time, or that all the satellite assemblies required are loadable and fully signed.

It turned out that the code was looking for resources named "controller.XXX.resources" whereas ResGen was creating them "XXX.resources". The solution was to use the RootNamespace element in the MSBuild file, i.e.

<PropertyGroup>
<RootNamespace>controller</RootNamespace>
</PropertyGroup>

Monday, November 19, 2012

Creating an IStream from a resource

In Win32, suppose you have an application resource (added with the resource compiler) and you want to open an OLE IStream interface on it. One reason might be to load an image with GDI+.
I initially made my own IStream implementation to provide read-only access to the resource data but I eventually decided to do the following, which is less code but does make a copy of the resource. The API is 'inspired by' the Shell's CreateStreamOnHGlobal function.

HRESULT CreateStreamOnResource(LPCTSTR name, LPSTREAM* stream) {
 HINSTANCE hInst = GetModuleHandle(0);
 return CreateStreamOnResource(hInst, name, stream);
}

HRESULT CreateStreamOnResource(HINSTANCE hInst, LPCTSTR name, LPSTREAM* stream)
{
 assert(hInst != 0);
 assert(name != 0);
 assert(stream != 0);
 *stream = NULL;
 HRSRC hC = FindResource(hInst, name, RT_RCDATA);
 if (hC) {
  // This is not really a HGLOBAL http://msdn.microsoft.com/en-us/library/windows/desktop/ms648046(v=vs.85).aspx
  HGLOBAL hG = LoadResource(hInst, hC);
  if (hG) {
   void* bytes = LockResource(hG);
   ULONG size = SizeofResource(hInst, hC);
   // Create a new empty stream.
   HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream);
   if (SUCCEEDED(hr)) {
    ULONG written;
    // Copy the resource into it.
    hr = (*stream)->Write(bytes, size, &written);
   }
   return hr;
  }
 }
 return E_INVALIDARG;
}
It should have been even easier - just get an HGLOBAL with LoadResource and pass it to CreateStreamOnHGlobal but LoadResource does not really return a handle to global memory so I needed to make the additional steps of creating a new stream, locking the resource and copying its data. I think I remember in the Win16 days you really did have to worry about loading and unloading resources from the segmented .exe but these days I think it all just gets mapped anyway.

Thursday, November 1, 2012

ListView and custom Cells

If you want to display a 'complex object' in a ListView, specify it as a parameter, for example
ListView<Thing> listView = new ListView<>();
However this only displays the result of calling Thing.toString() on the objects. To show more complex information you need to customise the ListCell. Start by providing a factory which creates new, customised cells.
listView.setCellFactory(new Callback<ListView<Thing>, ListCell<Thing>>() {
 @Override
 public ListCell<Thing> call(ListView<Thing> p) {
  return new ThingCell();
 }
});
JavaFX maintains some kind of relationship between ListCells and items in the list; it seems to be roughly one cell per visible row, not one cell per item in the list. You need to override updateItem() in Cell to attach a list item to a cell.
public class ThingCell extends ListCell<Thing> {
 @Override
 protected void updateItem(Thing t, boolean isblank) {
  super.updateItem(t, isblank);
  ...
 }
}
In other words, JavaFX uses the factory to create some cells, then attaches the list's contents to them. As the list is scrolled, different objects will be attached in turn. Bear in mind, t may be null - either because you've added a null object to the list, or because JavaFX wants a cell to suitable for displaying an empty row. In the latter case, isblank will be true. The appearance of the cell may be the same for either, in which case you can ignore isblank.
When an object is attached, remember to bind its properties to the cell, instead of just setting them. If the item then changes 'internally', the list will update automatically. For example, suppose Thing has a title property. If you do this:
protected void updateItem(Thing t, boolean isblank) {
 super.updateItem(t, isblank);
 if (t != null) {
  setText(t.titleProperty().get());
 }
 else {
  setText("");
 }
}
the item will display correctly when it is added to the list (and also if JavaFX re-attaches the objects), but if someone calls thing.titleProperty().set("New text") the list will not change. Instead, try
protected void updateItem(Thing t, boolean isblank) {
 super.updateItem(t, isblank);
 if (t != null) {
  textProperty().bind(t.titleProperty());
 }
 else {
  textProperty().unbind();
  textProperty().set("");
 }
}
Of course, if the list items never change after they've been added to the list, it isn't necessary to create the bindings and the first method can be used.

Tuesday, October 30, 2012

Cellular Automaton

This little cellular automaton was discovered by me in about 1995 but I'm sure someone else invented it before. If anyone knows its proper name I'd love to hear it. It can't be used to do anything clever but it does produce a surprising variety of patterns from a simple rule.
Each cell holds a value from 0-255 and has four neighbours. On each iteration, if the sum of all neighbours equals a given number ('the rule') the cell's value becomes 255. Otherwise it is decreased by 1 if it is greater than zero. If it's zero, then it stays as zero.
I've implemented it using HTML5 canvas, doing pixel-level access with ImageData.

See it here. It works on the 'modern' browsers that I've tested; Firefox, Safari and Chrome. It ought to work on IE9 and above and maybe Opera.
A quick note on the implementation:
I created a 2d context for the canvas element
var canvas = document.getElementById("ccc");
var ctx = canvas.getContext("2d");
Then an ImageData to cover the whole canvas.
var imd = ctx.createImageData(canvas.width,canvas.height);
I drew the image with
ctx.putImageData(imd, 0, 0);
I didn't work directly with the ImageData's data, which is always in 32-bit RGBA format. Instead I created a Uint8Array with 8 bits per pixel (I only needed to store 0-255), then converted it to image format as follows
function convi(imd, data) {
 var i;
 var out = imd.data;
 for (i=0; i<data.length; ++i) {
  out[i*4] = out[i*4+1] = out[i*4+2] = data[i];
  out[i*4+3] = 255;
 }
}
I just converted the 0-255 to a greyscale but here would be the place to implement a colour look-up table and get a nice palette.

Sunday, October 28, 2012

JavaFX Markdown Viewer


Introduction

I wanted a simple application to view markdown files. This is a plain-text format which reads naturally as it stands, but also can readily be converted to HTML. There are plenty of Java markdown processors available so I thought I would use the WebView component provided by JavaFX for display. The whole project is just then a bit of glue between a markdown processor and a display component. I used MarkdownPapers and JavaFX 2.2. The IDE was NetBeans 7.2, though I did not use anything specific to the IDE. In terms of specification, I just wanted to be able to view multiple files at once, and to have the display update automatically if any file changed on disk.

The User Interface

I set this up as simply as possible. There's a menu bar, then a tab pane which fills the rest of the window. Each document displays in a separate tab. Each tab contains a single WebView as its content pane. Details of this are included later.


I generated the UI with code rather than FXML; probably it would be better to use the latter for a more complicated interface.
// Create all menu items.
Menu fileMenu = new Menu("File");
MenuItem fileOpenMenu = new MenuItem("Open...");
MenuItem fileExitMenu = new MenuItem("Exit");
Menu viewMenu = new Menu("View");
MenuItem viewRefreshMenu = new MenuItem("Refresh");
CheckMenuItem viewAutoRefreshMenu = new CheckMenuItem("Auto Refresh");

// Assemble the menu bar
fileMenu.getItems().addAll(fileOpenMenu, new SeparatorMenuItem(), fileExitMenu);
viewMenu.getItems().addAll(viewRefreshMenu, viewAutoRefreshMenu);
MenuBar menuBar = new MenuBar();
menuBar.getMenus().addAll(fileMenu, viewMenu);

Rendering the Content

This was straightforward. I set up a reader to open the markdown file (using the platform's default encoding.) I created a parser to process the text into a MarkdownPapers Document object, then converted this to an HTML string in a StringWriter. The document only generates the body text, so I put some HTML tags either side of this to make it into a 'proper' document.
FileReader reader = new FileReader(filename);
StringWriter writer = new StringWriter();
Parser parser = new Parser(reader);
Document document = parser.parse();
// Add a minimal html skeleton.
writer.append("<html><head></head><body>");
document.accept(new HtmlEmitter(writer));
writer.append("</body></html>");
return writer.toString();
Note that there's no error handling at all here. Any exceptions are caught by the surrounding code (see later) but the FileReader could be left open if there is a parsing error. This should really be protected with try/finally blocks.

Displaying

Each WebView control has an associated WebEngine. The WebEngine accepts content in string form; it then processes this and passes the data onto the view to display.
final WebEngine webEngine = view.getEngine();
webEngine.loadContent(content, "text/html");
There's a slight issue with this; WebView is a fully-featured web-browser component, so clicking on an external link will load up an URL. I implemented a subclass of HtmlEmitter to replace any non-local links with '#', but I do not discuss that here.

Threading

Reading and parsing the file could take some time, so it shouldn't be done on the FX application thread.
However all updates to controls must be done on the application thread. A solution is to use the facilities from javafx.concurrent, specifically Task. I created a Task object to read and parse the markdown file, returning the HTML string. I then added a handler to the task to respond once the work is done. This sends the content to the WebEngine. Converting the HTML for the view is done internally by the WebView/WebEngine on a different thread, so I didn't need to worry about that. I also added a failure handler which will catch any Exceptions thrown by the task. In this case I just told the WebView to display the exception as text. So, the loading, rendering and display code looks like this.
Task<String> reloader = new Task<String>() {
    @Override
    protected String call() throws Exception {
        FileReader reader = new FileReader(filename);
        StringWriter writer = new StringWriter();
        Parser parser = new Parser(reader);
        Document document = parser.parse();
        // Add a minimal html skeleton.
        writer.append("<html><head></head><body>");
        document.accept(new HtmlEmitter(writer));
        writer.append("</body></html>");
        return writer.toString();
    }
};
// Succeeded, show the content as html
reloader.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
    @Override
    public void handle(WorkerStateEvent event) {
        // Get the string returned by the task body.
        final Object value = event.getSource().getValue();
        if (value != null) {
            webEngine.loadContent(value.toString(), "text/html");
        }
    }
});
// Failed, show exception as plain text
reloader.setOnFailed(new EventHandler<WorkerStateEvent>() {
    @Override
    public void handle(WorkerStateEvent event) {
        webEngine.loadContent(event.getSource().getException().toString(), "text/plain");
    }
});
Once the reloader object is set up, it can be run. The simplest way is to start a new thread.
new Thread(reloader).start();
I actually used an ExecutorService from java.util.concurrent to keep control of thread creation. The loading and processing takes place on a separate thread, then the Task mechanism ensures that the handlers are always called on the application thread.

Displaying a Document

Combining the previous steps, when the user selects a file, I
  • Created a new tab in the tab pane
  • Set the File as a property on that tab
  • Started a reloader task to get and display the content
I tracked the File's last modified time, also as a property of the tab. This is used when refreshing a tab's contents to avoid extra work if the file hasn't changed.
Setting properties on the Tab itself is a useful way of attaching some state without having to subclass Tab or maintain a separate look-up table. I used objects as keys (I could have used Strings instead.)
private static final Object SOURCE_FILE = new Object();
private static final Object UPDATE_TIME = new Object();
Then, I can read or write them as follows.
tab.getProperties().put(SOURCE_FILE, filename.getAbsoluteFile());
...
final File filename = (File) tab.getProperties().get(SOURCE_FILE);
My code to create a new tab is as follows.
private void openFile(File filename) {
    Tab tab = new Tab();
    tab.getProperties().put(SOURCE_FILE, filename.getAbsoluteFile());
    WebView wv = new WebView();
    tab.setContent(wv);
    tab.setText(filename.getName());
    wv.setContextMenuEnabled(false);
    tabPane.getTabs().add(tab);
    tabPane.getSelectionModel().select(tab);
    loadTabContent(tab);
}
where loadTabContent() reads the filename from the tab's properties and starts the load task as described above. To reload a tab's contents I just needed to call loadTabContent() again; it's self-contained. The function is shown below, omitting the Task creating code for brevity. This includes code to check if the file's been modified since it was last loaded.
private void loadTabContent(Tab tab) {
    final File filename = (File) tab.getProperties().get(SOURCE_FILE);
    Object updateObject = tab.getProperties().get(UPDATE_TIME);
    boolean needsReload = true;
    if (updateObject != null) {
        long updateTime = (Long) updateObject;
        needsReload = updateTime != filename.lastModified();
    }
    if (needsReload) {
        tab.getProperties().put(UPDATE_TIME, filename.lastModified());
        Task<String> reloader = ...;
        // Actually do the work on a different thread.
        executor.submit(reloader);
    }
}
Note that UPDATE_TIME is null the first time around so I checked for that, and forced an update if it is not set.

Refresh and Auto-refresh

Given the loadTabContent method above, implementing the refresh menu item was easy.
private void onRefresh(ActionEvent t) {
    Tab tab = tabPane.getSelectionModel().getSelectedItem();
    if (tab != null) {
        loadTabContent(tab);
    }
}
I just checked that tab isn't null in case the user selects refresh when no tabs are open.
For auto-refresh, I set up a timer to periodically try to reload all the open tabs. Because the file update time is compared, if the tab doesn't need to be reloaded then not much extra work is done. This could be done with java.nio.file.WatchService but it seemed unnecessary for this application.
JavaFX doesn't seem to have the equivalent of javax.swing.Timer (maybe there's something in the javafx.animation package), so I used java.util.Timer instead.
private Timer autorefreshTimer = new Timer("autorefreshTimer", true);
As always there is a little bit of trickery to get the events to happen on the FX application thread.
private class RefreshTask extends TimerTask {
    @Override
    public void run() {
        if (Platform.isFxApplicationThread()) {
            onTimerTick();
        } else {
            Platform.runLater(this);
        }
    }
}
...
autorefreshTimer.schedule(new RefreshTask(), 0, REFRESH_INTERVAL);
When the timer fires, it calls the run() method on its own thread. The method realises it is not on the application thread and reschedules itself to run on the correct thread. This could also have been written as follows.
public void run() {
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            onTimerTick();
        }
    });
}
I preferred not to have the nested Runnables.
When the timer ticks, it was again simple to refresh all tabs, because it's always going to be on the Application thread.
private void onTimerTick() {
    for (Tab tab : tabPane.getTabs()) {
        loadTabContent(tab);
    }
}

Binding the User Interface

I set actions for each menu item using code like the following.
fileOpenMenu.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent t) {
        onOpen(t);
    }
});
This just connects each one to a 'top-level' method in the Application class (onOpen in this case.) I did this to separate the actual working code from the handler mechanism.
I wanted the Refresh menu to be unavailable if Auto-refresh was active, since it wouldn't do anything useful. This didn't need a handler, just a property bind.
viewRefreshMenu.disableProperty().bind(viewAutoRefreshMenu.selectedProperty());

Conclusion

The implementation was pretty straightforward; the main complication was making sure the correct thread was used for each activity. Future work could include
  • Better error handling.
  • Use FXML.
  • Implement a recently-used file list.
Full source code is available.

First!

I've never attempted a blog before but the idea of this one is that I can use it to note down stuff I've found out about computers and hopefully it will be of some use in the future.