HTML5 CSS Toolbar + zoomable workspace that is mobile-friendly and adaptive

I have been working on a prototype level editor for Rabbit Escape, and I’ve had trouble getting the layout I wanted: a toolbar at the side or top of the screen, and the rest a zoomable workspace.

Something like this is very common in many desktop applications, but not that easy to achieve in a web page, especially because we want to take care that it adapts to different screen sizes and orientations, and, for example, allows zooming the toolbar buttons in case we find ourselves on a device with different resolution from what we were expecting.

In the end I’ve gone with a grid-layout solution and accepted the fact that sometimes on mobile devices when I zoom in my toolbar will disappear off the top/side. When I scroll back to it, it stays around, so using this setup is quite natural. On the desktop, it works how you’d expect, with the toolbar staying on screen at all zoom levels.

Here’s how it looks on a landscape display:

and portrait:

Read the full source code.

As you can see from the code linked above, after much fiddling I managed to achieve this with a relatively small amount of CSS, and no JavaScript. I’m hoping it will behave well in unexpected scenarios, because the code expresses what I want fairly closely.

The important bits of the HTML are simple – a main div, a toolbar containing buttons, and a workspace containing some kind of work:

<div id="main">
    <div id="toolbar">
        <button></button><button></button><button></button><button></button><button></button><button></button><button></button><button></button>
    </div>
    <div id="workspace">
        <div id="work">
        </div>
    </div>
</div>

The keys bits of the CSS are:

/* Ensure we take up the full height of the page. */
html, body, #main
{
    height: 100%;
}

@media all and (orientation:landscape)
{
    /* On a wide screen, it's a grid with 2 columns,
       and the toolbar can scroll downwards. */
    #main
    {
        display: grid;
        grid-template-columns: 5em 1fr;
    }
    #toolbar
    {
        overflow-x: hidden;
        overflow-y: auto;
    }
}

@media all and (orientation:portrait)
{
    /* On a tall screen, it's a grid with 2 rows,
       and the toolbar can scroll right. */
    #main
    {
        display: grid;
        grid-template-rows: 5em 1fr;
    }
    #toolbar
    {
        overflow-x: auto;
        overflow-y: hidden;
        white-space: nowrap;
    }
}

That replaces an awful lot of code in my first attempt, so I’m reasonably happy. If anyone has suggestions about how to make “100%” really mean 100% of the real device width and height, let me know. If I do some JavaScript I can make Mobile Firefox fit to the real screen size, but Mobile Chrome (and, I assume, Mobile Safari) lie to me about the screen size when zoomed in.

maven-assembly-plugin descriptor for a simple tarball with dependencies

Today I was trying to make a simple tarball of a project + its dependent jar using the maven-assembly-plugin. I know this is a terrible way to do anything, but hey, just in case someone else wants to do something just as terrible, here are my pom.xml and assembly.xml (the assembly descriptor):

$ tree
.
├── assembly.xml
├── pom.xml
└── src
    └── main
        └── java
            └── AssemblyExample.java
$ cat pom.xml
<project
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <name>My Projects</name>
    <version>0.1</version>
    <build><plugins><plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2.1</version>
        <configuration><descriptors>
            <descriptor>assembly.xml</descriptor>
        </descriptors></configuration>
        <executions> <execution>
            <phase>package</phase>
            <goals><goal>attached</goal></goals>
        </execution></executions>
    </plugin></plugins></build>
    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.2</version>
        </dependency>
    </dependencies>
</project>
$ cat assembly.xml
<?xml version="1.0" encoding="UTF-8"?>
<assembly>
    <id>ap3</id>

    <formats>
        <format>tar.gz</format>
    </formats>

    <includeBaseDirectory>true</includeBaseDirectory>

    <dependencySets>
        <dependencySet>
            <outputDirectory>jars</outputDirectory>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>

</assembly>
$ mvn package
...
[INFO] Compiling 1 source file to /home/andrebal/Desktop/assemblyexample/target/classes
[INFO] 
...
[INFO] Building jar: /home/andrebal/Desktop/assemblyexample/target/myproject-0.1.jar
...
[INFO] --- maven-assembly-plugin:2.2.1:attached (default) @ myproject ---
[INFO] Reading assembly descriptor: assembly.xml
[INFO] Building tar : /home/andrebal/Desktop/assemblyexample/target/myproject-0.1-ap3.tar.gz
...
[INFO] BUILD SUCCESS
$ tar -tzf target/myproject-0.1-ap3.tar.gz 
myproject-0.1/jars/slf4j-log4j12-1.7.2.jar
myproject-0.1/jars/slf4j-api-1.7.2.jar
myproject-0.1/jars/log4j-1.2.17.jar
myproject-0.1/jars/myproject-0.1.jar

Blog aggregator/planet in WordPress using FeedWordPress

I used to run Planet Code using Venus but that started breaking recently with 500 errors for SNI-enabled sites, and it looks very unmaintained.

I considered some other static aggregators, but on shared hosting it’s hard to get the right Ruby version and gems installed and the like, so I went for another WordPress, and found the very nice FeedWordPress plugin to suck up all the feeds of coders somewhat related to ACCU and/or coding generally.

Let me know what you think.

Adding a day in Python datetimes – use timedelta, not the datetime constructor

If you want “tomorrow” in Python datetimes, don’t construct a datetime like this:

from datetime import datetime, timedelta
td = datetime.today()
tm1 = datetime(td.year, td.month, td.day + 1, 14, 0, 0)
# Don't do this!

Because it will work sometimes, but fail when today is the last day of the month:

Traceback (most recent call last):
  File "./tomorrow", line 6, in 
    tm1 = datetime(td.year, td.month, td.day + 1, 14, 0, 0)
ValueError: day is out of range for month

Instead, use Python’s timedelta, which is designed for this purpose:

from datetime import datetime, timedelta

td = datetime.today()
tm2 = td + timedelta(days=1)

print("tm2=%s" % str(tm2))

And it’s easier to read too.

Broken Levels Challenge – Egham Raspberry Pi Jam July 2017

Today at the Egham Raspberry Pi Jam we did two things:

1. The Broken Levels Challenge

Some nasty person came and broke our levels for our game Rabbit Escape and we need you to fix them!

To play this game you will need a PC version of Rabbit Escape, our Broken Levels, and the instruction sheets. Let us know how you get on!

2. Python Traffic Lights Programming Workshop

I ran a workshop to learn a bit of Python programming using this resource sheet Pi Stop Traffic Lights.

We had a lot of fun, and hopefully some people even learnt a little bit of coding.