Thursday, July 4, 2013

Adding keyboard shortcuts

Do you find it unusual that OmniGraffle has no keyboard shortcut for Group and Ungroup? So did I. Fortunately, you can add your own through OSX's System Preferences.

Open System Preferences, choose Keyboard, and then choose the Keyboard Shortcuts tab. Then within that tab, choose Application Shortcuts on the left:


The well on the right lists all the applications that you've added keyboard shortcuts to. To make a new one, hit the "+" button below it. A dialog will appear that allows you to define a shortcut.


In the Application dropdown at the top, choose OmniGraffle. Then, in the Menu Title field, type the menu name exactly how it appears in OmniGraffle's menus. And finally, in the Keyboard Shortcut field, type whatever key combo you want to use for that menu. Here I'm assigning Control+G to the command Group:


Once you hit Add, you'll see the shortcut is added to the OmniGraffle list of shortcuts:


When you go back to OmniGraffle, you'll see that the Group menu now has the Control+G shortcut added to it:


Follow the same process for adding Control+Shift+G to Ungroup. You can also use this process to change an existing menu's shortcut.

Wednesday, July 3, 2013

Use Duplicate instead of Copy/Paste

I'm so habituated to using Copy/Paste, but I'm trying to break that habit and use OmniGraffle's Duplicate command instead. The shortcut is Command+D.

It's one key-combo instead of two, but more importantly, it doesn't wipe out whatever you have on your clipboard.

And like Copy/Paste, it has a hidden feature. Let's say you duplicate an object, and then you move the duplicate directly below the original, leaving 20 pixels between the two objects. OmniGraffle will remember the duplicate's offset from the original, so when you duplicate that duplicate, its own duplicate will appear 20 pixels below it, and so on. After moving the first duplicate to where you want it, just hit Control-D over and over to create an equidistant row or stack of objects.

One shortcoming: there's no ability to duplicate an object such that the new object lands exactly on top of the old one. The duplicated object lands down and over from the original. Copy has a corresponding Paste in Place command which pastes the new object exactly on top of the copied one, but there is no Duplicate in Place option.

Not that it's hard to press Up-arrow + Left-arrow, but down and over is an inconvenient starting point when the intended offset is either directly below or directly to the right.

A powerful inspector: Canvas with Grid and Alignment open

Okay, enough of this AppleScripting for now. Back to the basics.

This is my goto inspector. I use it more than any other, and for laying objects out, it's indispensable. It's the Canvas inspector with Grid and Alignment locked open. (Double-clicking an inspector tab locks it open, allowing you to have multiple tabs open at once. Locked tabs are signified by the small green lock icon.)


In this post, I'll assume your units are set to pixels (unless otherwise specified), but the concepts are the same when set to any unit.

Canvas > Grid

First, if you are not snapping to a grid when drawing and arranging objects, start doing so. With snap-to-grid on and a grid spacing greater of 2 or more, if two objects look aligned, they are aligned. Also, it avoids having to put screen locations like "10.384 , 30.76" in your redlines. (I kid, but those long decimals drive me nuts.)

Speaking of that, a way to get rid of all of those messy fractional locations/dimensions in one fell swoop is this: select all objects, turn snap-to-grid on, set major and minor grid spacing to 1, and press the Align To Grid button. 

It's handy to have the Canvas > Grid Inspector always available. Usually I start with a grid spacing of 5 because it makes moving the selected object with the arrow keys reasonably fast and it's good for creating an initial layout. But when I'm especially impatient when moving an object a long distance with the arrow keys, I'll bump it up to 10 or 20. And when I'm refining the layout, I drop it down to 1.

Major and Minor grids

The minor grid steps setting for me is set to 1 for wireframes. Minor grid steps divides your major grid spacing by its value, so if your major grid spacing is 100 and your your minor grid spacing is 10, it creates a grid that is spaced 10 pixels apart. It's almost identical to having major grid spacing set to 10 and minor grid steps set to 1. 

I say "almost" because it's different if you are actually displaying the grid. If you turn Show Grid Lines on and then turn on Show Major, in the scenario above you'll see the major grid lines 100 pixels apart, and the minor grid lines 10 apart. The two types of grid lines are distinguished by the color chosen in the color wells next to them.

An example of where this is useful is designing a woodworking project, a task OmniGraffle is ideally suited for. Set your units to inches, your major grid spacing to 1, and your minor grid steps to 8. Then you'll get a grid displaying inches and eighths of inches, and objects snapping to every eighth-inch. And if you suddenly need sixteenths of an inch, change minor grid steps to 16.

Canvas > Alignment

I won't go into the alignment control (for aligning selected objects by their tops, centers, lefts, etc.) since that's pretty self-evident. But two sets of spacing controls are pretty useful, and behave completely differently.

First off, the layout of the Canvas > Alignment Inspector is confusing. The number fields between the two horizontal-spacing buttons and two vertical-spacing buttons have nothing to do with the buttons to the left of the fields; they affect only the buttons to the right of the fields.

The Spread-Evenly buttons

These buttons - to the left of the number fields - evenly distribute a set of selected objects between the leftmost (or topmost) selected object, and the rightmost (or bottommost) selected object. 

I don't use these buttons for wire-framing because the objects in the middle will likely have fractional values in their location properties. Instead I use the buttons to the right of the number fields.

The Offset-Horizontally/Vertically buttons

These buttons - to the right of the number fields - take the value in the field to their left and place that many pixels between each of the selected objects, distributing them horizontally or vertically starting with the leftmost (or topmost) object. The top button does horizontal spacing, and the bottom button does vertical spacing. This is useful when mocking up, say, a row of albums on a music site, or a list of social-network friends in a friends list.

The Create Shape commands

Note that these number fields in the Canvas > Alignment inspector have a secondary purpose - they affect the Create Shape Left, Create Shape Right, Create Shape Top, and Create Shape Bottom commands (located under Edit > Mouseless Editing, though you'll learn the shortcut keys rather than accessing them through menus).

These handy commands take the selected shape or group and create a duplicate of it a certain distance to the left, right, top, or bottom of the original. The keyboard shortcut is Command+Option+[any arrow key]. 

The horizontal distance between the original and the duplicate (for the Left/Right versions of this command) is determined by the top number field in this inspector, and the vertical distance between the original and the duplicate (for the Top/Bottom versions of this command) is determined by the bottom field in this inspector.

Monday, July 1, 2013

Applescript to draw a taxonomy from a JSON source.

This script outputs the exact same chart as the one in another post, but it takes a JSON source instead of the outline source. This is useful only if you have an automated way to create JSON. If you plan to hand-type it, you'd be better off with the script in this other post instead.

Here is sample output from this script. You can customize the appearance by changing the properties at the top of the script that start with "SETTINGS_":


The script expects a JSON file where each JSON object represents a node. Each object has (up to) two properties: "itemName" which is the label of the node, and (if the node has children)  "itemChildren" which contains the children of the node. Child nodes can have children of their own.

The script expects the file to be on your Desktop, and by default it needs to be named "drawtree.json" but you can change that in the settings at the top of the script.\

Here is the JSON that produces the chart above:

[
  {
    "itemName": "Rock/Pop",
    "itemChildren":
        [
      {"itemName": "Roots",
        "itemChildren":
        [
          {"itemName": "Cajun/Zydeco"},
          {"itemName": "Tex Mex"},
          {"itemName": "Swamp Pop"}
        ]
      },
      {"itemName": "Singer-Songwriter"},
      {"itemName": "Classic Rock",
        "itemChildren":
        [
          {"itemName": "AOR"}
        ]
      },
      {"itemName": "Art & Progressive Rock",
        "itemChildren":
        [
          {"itemName": "Rock Opera"},
          {"itemName": "New Prog"},
          {"itemName": "Krautrock"}
        ]
      },
      {"itemName": "Blues & Boogie Rock",
        "itemChildren":
        [
          {"itemName": "Boogie Rock"},
          {"itemName": "Southern Rock"}
        ]
      },
      {"itemName": "Glam"},
      {"itemName": "Hard Rock",
        "itemChildren":
        [
          {"itemName": "Post-Grunge"},
          {"itemName": "Instrumental Guitar Rock"},
          {"itemName": "Acid Rock"}
        ]
      },
      {"itemName": "Instrumental Rock"},
      {"itemName": "Pop",
        "itemChildren":
        [
          {"itemName": "Dance Pop"},
          {"itemName": "Teen Beat"},
          {"itemName": "Teen Idols"}
        ]
      },
      {"itemName": "Jam Rock"},
      {"itemName": "Latin Pop"},
      {"itemName": "Country Rock"},
      {"itemName": "Funk Rock"},
      {"itemName": "Metal",
        "itemChildren":
        [
          {"itemName": "Progressive Metal"},
          {"itemName": "Thrash/Speed Metal"},
          {"itemName": "Stoner Rock"},
          {"itemName": "Grindcore"},
          {"itemName": "Doom Metal"},
          {"itemName": "Pop Metal"},
          {"itemName": "New Wave of British Heavy Metal"},
          {"itemName": "Black Metal"},
          {"itemName": "Death Metal"},
          {"itemName": "Funk Metal"},
          {"itemName": "Industrial Metal"},
          {"itemName": "Christian Metal"},
          {"itemName": "Rapcore"},
          {"itemName": "Alt Metal"},
          {"itemName": "Metalcore"}
        ]
      },
      {"itemName": "Folk-Rock",
        "itemChildren":
        [
          {"itemName": "Political Rock"},
          {"itemName": "Celtic Rock"}
        ]
      },
      {"itemName": "Adult Alternative"},
      {"itemName": "Adult Contemporary",
        "itemChildren":
        [
          {"itemName": "Blue-Eyed Soul"},
          {"itemName": "Modern Folk"},
          {"itemName": "Lite Rock"},
          {"itemName": "Jazz Rock"}
        ]
      }
    ]
  }
]

IMPORTANT: this script requires the application "JSON Helper." This application is free in the Apple App Store, available under the Apple menu. (Search for "helper" and it's one of the first results.)

Script after the jump: