Andrew Aitken - Blog

Shooting Film

I’ve been interested in photography ever since I found my Dad’s old Praktica SLR. I was quite young at the time and would spend ages playing with it, turning the dials and noticing the shutter staying open that little bit longer. I didn’t have a clue what it all meant, but that just made it all the more fascinating.

It was almost 20 years later when a friend at work brought in his Canon DSLR. That sparked the interest again and I finally got my own DSLR, a Canon 500D. I played around with it for a while before realising I still had a lot to learn. I practiced using my camera in manual mode, learnt how the histogram worked and read some books on composition. But I still felt like I could do better.

Somewhere along the line I found out about fully manual, mechanical SLR cameras from the 80’s and 90’s. I decided to get one to force myself to work in manual mode and I ended up getting a Pentax MX with a 50mm f1.7 lens. I also booked myself on a course, at a local gallery Street Level Photo works, where I learned how to develop black and white film and make my own prints using an enlarger.

Pentax MX The Pentax MX - By Kinnerton - Wikimedia

The Pentax MX has a built in light meter to help get your exposure right, but it’s up to you to change the shutter speed and aperture (ISO isn’t a variable once you’ve put the film in the camera).

Hope Street, Glasgow Hope Street, Glasgow - Pentax MX - Ilford HP5 Plus 400

The first thing I noticed was the 50mm lens was much wider than the 50mm on my DSLR. The Canon 500D has a crop sensor which means you lose quite a bit of the frame compared to a normal 35mm camera. I loved being able to get more in the frame at a natural focal length, it also meant I had to get much closer if I wanted to fill the frame.

If your photographs aren’t good enough, you’re not close enough. - Robert Capa

I got my first roll of film developed by Ilford and was really happy with some of the results. After that I went on the course at Street Level and learned to develop the film myself. Working in a darkroom is strangely relaxing, it’s usually really quiet and the time just flies past.

Drinking Drinking - Pentax MX - Ilford HP5 Plus 400

I loved using this camera, unfortunately the shutter now tends to stick at lower shutter speeds, even after a service from a local repair shop.

Not knowing what shots you have until you get them developed adds a little bit of excitement when you see the negatives for the first time. Obviously that’s not very good if you are trying to get an important shot, but when taking photos for fun, I found it helped me focus more on taking the shot and to try and make sure I got it right first time.

Shooting film is considered a bit of a hipster thing to do now, but I really enjoy the process and I think understanding where photography came from can really help you appreciate where it is now. That’s not to say I don’t use my digital camera anymore, it certainly has it’s advantages, but I enjoy having the choice.

Paris Mark during work trip to Paris - Canon 500D

Playing

When I got into film I discovered the “just for fun” side of photography, where goal wasn’t necessarily to take a great picture but to do it in a different or interesting way. My first venture into this was when I bought a Holga medium format camera and a Holga wide angle pinhole camera. The pinhole photos have an interesting look with their infinite depth of field and massive vignetting.

Pinhole View from my old flat - Holga 120 WPC

After a few rolls of medium format had been through my Holga, I modified it to take 35mm film. This has the cool effect of exposing the film sprocket holes and includes them in the photo. The focus through the cheap lens of the Holga 120 GN isn’t great, but that’s not the point.

Old Fountain Old fountain - Holga 120 GN - using 35mm film

Read more →

Deploying my blog with Travis

I was curious about having my blog deployed whenever I push a commit, so after a bit of googling I found this handy tutorial by Mathieu Leplatre.

There were a few differences, I am using the GitHub user pages, where he was using a project page, so my blog output needs to sit on the master branch and not gh-pages.

I’ll just show what I had to do differently, so here is my .travis.yml file. I had a few issues with it, but nothing YAML lint and Travis WebLint couldn’t sort out.

language: python
python: 2.7
env:
  global:
    secure: "my-encrypted-token (truncated for size)"
branches:
  only:
    - source
install:
  - "pip install -r requirements.txt"
script:
  - "make publish github"

And my modified Makefile

github: publish
    cp .travis.yml output/
    ghp-import -b master $(OUTPUTDIR)
    @git push -fq https://${GH_TOKEN}@github.com/$(TRAVIS_REPO_SLUG).git master > /dev/null

Key differences are the -b master parameter passed to ghp-import which tells it to update the master branch. I also copy my .travis.yml file to the output as it tells Travis only to build the source branch and I don’t want it trying to rake my html.

You can see it all on my GitHub page.

Read more →

Creating a Custom Section in Umbraco 6 - Part 2: The Tree

The tree needs a little bit more work to implement than the application.

Here is the initial class declaration.

[Tree("appAlias", "treeAlias", "Tree Title")]
public class MyApplicationTree : ITree
{
}

Tree Attribute

The Tree attribute takes similar parameters to the Application attribute.

  • appAlias - The alias of the application this tree belongs too.
  • alias - The alias for this tree.
  • title - The title of the tree, not entirely sure if this is used.

ITree

This has a few properties and methods we need to implement.

public interface ITree
{
    string app { set; }
    int id { set; }
    void Render(ref XmlDocument Tree);
    void RenderJS(ref StringBuilder Javascript);
}

The first two are easily implemented with an automatic properties.

public string app { get; set; }
public int id { get; set; }

We use the RenderJS method to add javascript to the backoffice that will allow us to change the content on the right hand side frame. We will call this when we click on a node in the tree.

public void RenderJS(ref StringBuilder javascript)
{
    javascript.Append(@"function openLocation(url) { parent.right.document.location.href = url; }");
}

Lastly we need to build our actual tree in the Render method. We need to build it in an XmlDocument and it’s fairly straightforward once you’ve done it a few times.

public void Render(ref XmlDocument tree)
{
    // Add our base elements
    XmlNode root = tree.DocumentElement;

    if (this.id == -1)
    {
        // Get data from somewhere or create a static tree root
        // Add 10 nodes for an example
        for (int i = 1; i <= 10; i ++)
        {
            XmlElement treeElement = tree.CreateElement("tree");
            treeElement.SetAttribute("menu", string.Empty);
            treeElement.SetAttribute("nodeID", i.ToString());
            treeElement.SetAttribute("text", i.ToString());
            treeElement.SetAttribute("action", string.Format("javascript:openLocation('/Path/To/Document.aspx?id={0}');", i));
            treeElement.SetAttribute("src", string.Empty);
            treeElement.SetAttribute("icon", "myClosedIcon.png"); // Icons go in ~/Umbraco/Images/Umbraco/
            treeElement.SetAttribute("openIcon", "myOpenIcon.png");
            treeElement.SetAttribute("nodeType", "tree");

            root.AppendChild(treeElement);
        }
    }
    else
    {
        // We'll come to this later.
    }
}

This should create 10 nodes in your tree, you will probably want to switch this to get data from a database or something similar. Or you may have a few static root nodes that then load data when expanded.

Child Nodes

To load child nodes in a tree, you call the tree again with the id of the parent node. This is where that if (this.id == -1) comes in. You set the tree to call in the src attribute of the node.

treeElement.SetAttribute("src", this.GetServiceUrl(i));

// ... snip ...

private string GetTreeServiceUrl(int nodeId)
{
    TreeService treeService = new TreeService(nodeId, "treeAlias", false, false, TreeDialogModes.fulllink, this.app);
    return treeService.GetServiceUrl();
}

We then catch this like so:

public void Render(ref XmlDocument tree)
{
    // Add our base elements
    XmlNode root = tree.DocumentElement;

    if (this.id == -1)
    {
        // Get data from somewhere or create a static tree root
        // Add 10 nodes for an example
        for (int i = 1; i <= 10; i ++)
        {
            XmlElement treeElement = tree.CreateElement("tree");
            treeElement.SetAttribute("menu", string.Empty);
            treeElement.SetAttribute("nodeID", i.ToString());
            treeElement.SetAttribute("text", i.ToString());
            treeElement.SetAttribute("action", string.Format("javascript:openLocation('/Path/To/Document.aspx?id={0}');", i));
            treeElement.SetAttribute("src", string.Empty);
            treeElement.SetAttribute("icon", "myClosedIcon.png"); // Icons go in ~/Umbraco/Images/Umbraco/
            treeElement.SetAttribute("openIcon", "myOpenIcon.png");
            treeElement.SetAttribute("nodeType", "tree");

            root.AppendChild(treeElement);
        }
    }
    else
    {
        // Get items that have a parent node of this.id
        // Just as an example
        XmlElement childElement = tree.CreateElement("tree");
        childElement.SetAttribute("menu", string.Empty);
        childElement.SetAttribute("nodeID", 99);
        childElement.SetAttribute("text", "Child of " + this.id.ToString());
        childElement.SetAttribute("action", string.Format("javascript:openLocation('/Path/To/AnotherDocument.aspx?id={0}');", this.id));
        childElement.SetAttribute("src", string.Empty);
        childElement.SetAttribute("icon", "icon.png");
        childElement.SetAttribute("openIcon", "icon.png");
        childElement.SetAttribute("nodeType", "tree");

        root.AppendChild(childElement);
    }
}

Need More Node Ids?

The basic tree works really well if you have a unique Id for every item and hierarchy is defined within that by parent Ids, like the content in Umbraco content. But if you need multiple roots nodes, each showing items that may have conflicting Ids, then you can add another tree.

By default all trees for an application will be added to the root, this might be what you want, but if it’s not, there is an overload for the Tree attribute to stop it being loaded.

[Tree("appAlias", "treeAlias", "My Child Tree", ".sprTreeFolder", ".sprTreeFolder_o", "", false, false)]

It’s the last boolean parameter which tells Umbraco not to initialize the tree, so it won’t be added to the root. You can then change your src attributes on your nodes to point to the new tree.

private string GetTreeServiceUrl(string treeAlias, int nodeId)
{
    TreeService treeService = new TreeService(nodeId, treeAlias, false, false, TreeDialogModes.fulllink, this.app);
    return treeService.GetServiceUrl();
}

Context Menus

You can control the context menu available on a node by setting the menu attribute on the node. This isn’t something I have implemented yet, there is more information for this available here.

Read more →

Creating a Custom Section in Umbraco 6 - Part 1: The Application

I’ve been doing a bit of work lately creating a custom section in an Umbraco v6.1 install. I needed a nice tree for my custom section, so after a lot of googling and digging through the Umbraco source, I managed to get it all working nicely. I’ve put this guide together to hopefully make the process a little easier for myself and any other weary internet travellers who happen to stumble upon it.

The Application

This is much easier now in version 6, to add a new application you just new to create a class that implements umbraco.interfaces.IApplication and has the Application attribute.

[Application("alias", "Real Name", "images/nada.gif", 10)]
public class MyApplication : IApplication
{
}

IApplication

This interface actually has no definitions, so it’s a piece of cake to implement :)

Application Attribute

This takes a few parameters:

  • alias - Your application alias, usually starts lowercase eg “myApplication”
  • name - The nice name for your application, e.g. “My Application”
  • icon - The icon to be displayed in umbraco, you’ll need to do a bit of css jiggery pokery to get it right. I’ve used nada.gif then added my icon to the existing tray sprite and added a css class which matches the application alias to position it.
  • sortOrder - You can put it at the start or in between existing apps, I set mine to 10 to make sure it was at the end.

applications.config

That should be your app set up, when you first run umbraco after creating that class, it should update the ~/config/applications.config automatically for you. I’ve found changing anything defined in the Application attribute after this point won’t be reflected in the applications.config, so if you need to make any changes, remember check that the applications.config reflects the new values.

Making it visible

When you start up Umbraco, your application should be installed but you will need to allow yourself access before it is visible. In the Users section, select your user from the Users tree and tick the box next to your new application.

Application Name

At the top of the tree on your application page, you will see that it is showing your application alias instead of the name, to update this you need to add a key setting to ~/umbraco/Config/Lang/en.xml (swapping “en” for whatever language you are using).

<area alias="sections">
    ...
    <!-- Add this line -->
    <key alias="myApplication">My Application</key>
</area>

Your app should now have a nice name.

I will post a guide to the trees later this week.

Read more →

Nearly there

Well, I’ve updated the site. Unfortunately all my posts are now marked as being created in the last few days. So that’s on my “to fix” list.

In the mean time though, you can now browse my site on a phone.

Read more →