Tag Archives: TeenyTyper

Tales of the TeenyTyper #3 – The ActionBinder

In building the TeenyTyper, I decided that I wanted  to avoid the usual window decorations (like a close button).  A special key combination of <CTRL-D> would be instead used to shut down the toy once we’d finished playing.

I’ve tried implementing  Swing’s KeyListener interface in the past, but I’ve experienced the occasional KeyListener event not firing when it should have.  Sure enough, my first attempts at using a KeyListener misbehaved as expected.  A quick trawl of StackOverflow, and I hit gold.   Seems that I’d be far better off using key bindings instead.

So, in essence, I’m binding a particular action to perform for a given Swing component every time the component catches a relevant keystroke event.  Below is the reusable library function I settled on to establish this relationship:

public static void bindKeyStrokeToAction(
                     JComponent component,
                     String keyStrokeLabel,
                     KeyStroke keyStroke,
                     AbstractAction actionToPerform) {

  InputMap inputMap = component.getInputMap(
    JComponent.WHEN_IN_FOCUSED_WINDOW
  );

  inputMap.put(
    keyStroke,
    keyStrokeLabel
  );

  component.getActionMap().put(
    keyStrokeLabel,
    actionToPerform
  );
} 

I’m not a big fan of that keystroke label requirement in the mapping. I have no need for the string itself once the mapping has been established. The string really could be anything for all I care (at least for this application).  To hide this string detail, and make the interface even easier to use, I implemented a wrapper to auto-generate a unique string mapping via Java’s UUID functionality like so:

public static void bindKeyStrokeToAction(
                     JComponent component,
                     KeyStroke keyStroke,
                     AbstractAction actionToPerform) {

  bindKeyStrokeToAction( 
    component,
    UUID.randomUUID().toString(),
    keyStroke,
    actionToPerform
  );
}

So, implementing an action that shuts the TeenyTyper down gracefully when <CTRL-D> is pressed on the editor pane is achieved with the following call:

    ActionBinder.bindKeyStrokeToAction(
        components.editor, 
        KeyStroke.getKeyStroke(
            KeyEvent.VK_D, 
            KeyEvent.CTRL_DOWN_MASK), // <CTRL-D>
        new AbstractAction() {
          private static final long serialVersionUID = 1L;

          public void actionPerformed(ActionEvent arg0) {
            System.exit(0);
          }
        }
    );

And that’s it. No more KeyListener event misfire blues for yours-truly.

Keybind your actions long and prosper.

Advertisements

Tales of the TeenyTyper #2 – The git CPAP trap!

I currently class myself as a novice in distributed git repositories. In my extant work role, I’m using git for source version control, but I’m operating as a git project user group of one,  as my supervisor refuses to use any form of source control other than simply copying the entire source folder.

Being rather pragmatic about it all, I kept our git setup as simple as the situation needed.  I’ve gotten by just fine with a single repository on my work machine with a branch per developer that I can occasionally merge and redistribute from.

One of the things I’m learning out of my TeenyTyper experience is how to use distributed git repositories for my project via GitHub.  My early experiments have been making a mess of the commit history (no, don’t look!).

The problems started not long after I took my clone of the TeenyTyper repository hosted with GitHub.  I couldn’t push my recent commit back to GitHub, despite the fact that all I’d read had  me believing that I should be able to.  I eventually worked around it by doing a merge of the remote repository into the local repository.  The merged version I could push successfully back to GitHub. This seemed to happened rather non-deterministically, and irked me because I shouldn’t actually need to merge these changes.

I went pouring through the git manual this morning, and now I see what I was doing to make all that mess. It makes sense now that I see the process, but as a novice I missed initially what I was doing to cause the issues in the first place.

The essence of my problem was that I was doing the following sequence of activities:

  1. (change some repository managed files locally)
  2. git add <changed files>
  3. git commit
  4. git push <remote-repository> <local-repository>
  5. (some more changes forgotten in the first commit)
  6. git commit –amend
  7. git push <remote-repository> <local-repository>

The error returned looks something like this:

To git@github.com:user/repo.git
! [rejected] branchname -> branchname (non-fast forward)
error: failed to push some refs to 'git@github.com:user/repo.git'

I see now that a “commit amend” does not modify an existing git commit object, it replaces that commit object with an entirely new one, based on the old. You can confirm this for yourself easily simply by looking at the commit hash before and after the amend.  The second push attempt fails  because there is no common base for the two repositories to base the push on, as that original commit was replaced (only) locally by the “commit amend”.

My take-away lesson from all this is to self-censor any attempts at amending commits that have been sent off already to a remote repository. The convenience of tweaking a commit with an amend is just not worth the effort that I need to go through to get the repositories back on the same page.

It’s a trap, and it’s triggered by the sequence of (C)ommit, (P)ush, (A)mend, (P)ush git commands.  I’m now wishing they’d called a “commit amend” a “commit replace” to better mesh with my intuition on the  meaning of amend.  Ah well, we live and learn.

Push git commits long and prosper!

Tales of the TeenyTyper #1 – A Beginning

TeenyTyper is a small software project I’ve just started up to satisfy a number of itches that need scratching. It’s allowing me to:

  • Get some Java programming in, as my recent day job is the .NET family, and I’m finding my Java skills are on the wane without love.
  • Sorting out in my own head how a distributed Git code repository model actually works.
  • Plug a hole where I am torn over allowing my very young children to play with my computer, and denying them so I can guarantee a working machine when I come back to it.
  • Explore concepts around interest-based learning, espoused by the late educator John Holt.

It’s a kind of synchronisation of a lot of thoughts I’ve been toying with. Things like recognising a personal truth in John Holt’s writing in how my own very young children are engaging with the world; trying to make sense of it, most especially in watching then mimicking the adults around them do adult things.  It’s also an “ahh-hah” moment in hearing the discussion on the war on general computing described by Cory Doctorow:

In hearing Corey talk, I finally got conscious over something I’ve known subconsciously for a while. I love my computer because it’s a general-purpose device.  If there’s a turing-complete problem I want to solve, my computer can support my will to see it solved.  Such power is causing me a real challenge, as my darling children see me doing stuff on the computer, and also want to do the same thing themselves.

In reading John Holt’s work, the idea of children contributing to their learning of language through their explorations of his electronic typewriter stuck somewhere in the back recesses of my mind.

Eventually, my subconscious hit me with one of it’s typical “Ding, I’m done!” moments pointing out that I could write a kind of electronic typewriter for my kids. It could act to turn my overly powerful general purpose computing device into a kind of gimped electronic typewriter that the kids could play with until they got bored and ran off.  Once gone, I could wave TeenyTyper goodbye, and get back to my first love of exploring what I can build with general purpose computing. I found this idea compelling enough to start a new project.

So, TeenyTyper is currently being written in Java 6, using the Swing toolkit for its GUI. I’ve released the code under the Creative Commons Attribution-ShareAlike 3.0 Unported License.

Creative Commons Licence

The open choice of licence matches my desire to let these toy projects out to play all by themselves, coupled with my realisation that GitHub pretty much demands a model of letting the code all just hang out there for everyone to see.

The plan from this point on is to post new articles on TeenyTyper as I learn new things that I’d like to share.  This first post is deliberately a scene-setter so I don’t need to re-introduce the background to the toy in each new post.

So, until my next post, type long and prosper.