ui

An inactive checkbox is always a bit of a mystery to me.
Why is it inactive? How do I get it to activate so I can select it? More often than not, it takes me a couple of tries fiddling around with other preferences to finally activate the checkbox and be able to select it.
It shouldn’t be that way.

And now I realize I’ve been guilty of having such an inactive checkbox in Yoink‘s preferences myself:

Yoink 3.2 Preferences Inactive CheckboxThe inactive checkbox “Show window near mouse pointer (…)” is inactive and needs extra steps to be activated

It’s exactly what I dislike. What was I thinking?
As a new user who has no idea how these preferences are connected, you just don’t know how to get that checkbox active and, more importantly, how to change the setting available behind the inactive checkbox.
In the worst case, it’d take three steps to activate it. You’d have to:

  1. Select the checkbox “Automatically show when” (if it wasn’t active before)
  2. Change “mouse pointer is at edge of screen” to “drag starts”
  3. and then you’d finally be able to access the newly active checkbox
If I launch Yoink for the first time, I have no idea what’s going on. That’s not a very good user experience.
So with the upcoming update v3.2.1, the checkbox will always be active, and it’s much clearer how these two options are connected:

Yoink 3.2.1 Preferences Active CheckboxIn Yoink v3.2.1, the checkbox is always accessible, eliminating extra steps to be able to select it.

Obviously, not all cases are the same and sometimes, in some places, there might be a good reason to have a checkbox inactive.
But here, it was clearly the wrong choice.

[Update 27.10.2016: I published a follow-up here.]

Eternal Storms Software Logo

– – – Do you enjoy my blog and/or my software? – – –

Stay up-to-date on all things Eternal Storms Software and join my low-frequency newsletter (one mail a month at most).
Thank you 🙂

Read more

ESSSquareProgressIndicator animating

What Is ESSSquareProgressIndicator?

It’s an indeterminate progress indicator originally developed for the iOS game ZEN.

It uses Core Animation (specifically, CAShapeLayers) to do its job and it’s pretty straight forward.

CGPathRefs, CAShapeLayer

CAShapeLayer has two animatable properties – -strokeStart and -strokeEnd (with a minimum value of 0.0 – start of path – and 1.0 – end of path). Going beyond 1.0 or below 0.0 doesn’t work.

So when trying to animate those values along a rectangular path – which was the first thing I tried when creating this – you do get a nice animation, but it ends at the 0.0/1.0 (which is, basically, the same) mark. So you end up with something like this:

glitchy progress indicator animation

The goal, then, was to animate beyond 1.0. The solution I came to – I’m sure there are other ways – was to use a second CAShapeLayer that animated alongside the first for the last/first part of the animation.

For a square, the values of the CAShapeLayer’s -strokeStart and -strokeEnd are as follows (starting at the top left corner):

CAShapeLayer strokeStart strokeEnd values

The CGPath begins and ends in the top left corner because I drew the path that way (you could make it start in the lower left corner or in the middle of a side, it all depends on where you start the CGPath with CGPathMoveToPoint).

The progress indicator starts at the middle of the left line and reaches to the middle of the top line. These are the two CAShapeLayers at work. The left part is one shape layer, the top line is another. I’ll do this in pictures I drew in code so it’s simpler to understand (the lines represent where the layer animated to, the dots are the invisible rest of the square).

Animating

Animation Part 1We start at this position. The line to the left is layer2(strokeStart:0.875, strokeEnd:1.0), the line at the top is layer1(strokeStart:0.0, strokeEnd:0.125).

Animation Part 2The transition to this is the reason we need two layers as we can not animate one layer beyond the 1.0 value.
So we animate layer2 to (1.0, 1.0) and at the same time animate layer1 to (0.0, 0.25) which makes it look like one line moving.

Animation Part 3This next part is easy. We animate layer1 to (0.75, 1.0).

Animation Part 4Lastly, we animate with two layers again to get to the initial position so we can repeat the whole thing from there on.
We animate layer2 from (0.75, 1.0) to (0.875, 1.0) and layer1 from (0.0, 0.0) to (0.0, 0.125) at the same time, again making it look like one line moving.

The Source Code

The repository (a sample iOS app, but the class works the same on OS X) is available on Github.

It was developed for iOS 7.1 but should work on earlier systems, and has been tested on OS X Yosemite, but should work on earlier systems as well.

You just drop in an ordinary UIView or NSView and set its class to ESSSquareProgressIndicator. Done. You can then set the color and stroke width right within Interface Builder thanks to the fairly new Xcode macros IB_Designable and IBInspectable.

Open Source

I have some more source code available here (or directly on my github profile page) if you’re interested. If you have any questions or feedback regarding this progress indicator, please be sure to mail or tweet me 😉

Enjoy!

—-
My name is Matt, I’m the developer of Eternal Storms Software. If you’d like to comment, you can catch me on twitter here: [twitter-follow screen_name=’eternalstorms’ show_count=’yes’] or by eMail.

Read more

useless error message

“Positive” Error Messages

For me, “positive” error messages are alerts that tell you something “failed” because the user has already done it before and so there’s no use in doing it again.

Like in the example screenshot above. The user added, at some point in history, a photo to their favorites. Now they stumble upon this photo again in some user’s photo stream and add it to their favorites again. And this error pops up, telling them they’re an idiot for not remembering it’s in their favorites already.

Necessity of Feedback

Giving the user feedback on what they do is very important, no argument there. But you have to be careful not to cross the line from giving helpful feedback to just being outright obnoxious or worse, unnecessarily interrupt the user’s workflow.

Alert panels are a good way of telling the user something went wrong when it needs their (immediate) attention. But halting the application to tell the user something has already been successfully done – what’s the use in that?

Example: flickery

flickery is the app where I run into this most often. “Photo already in favorites”. “Already in Group”. “Already in Set”. “Already in Gallery”. “Already member of the group”. etc.

Early versions of flickery did have these alerts in them. Actually, I hadn’t given it much thought at the time. But using the app a lot myself it quickly became clear to me that it’s just plain annoying.

flickery does have a “flying” animation when adding photos to favorites, sets, groups and galleries. Isn’t that all the feedback necessary in that case?
The user is informed something happened and that’s what counts. And if it’s already in there – who cares? Putting it in there was the point all along.

I do the same thing in ScreenFloat. When you add a shot to a category and it’s already in there, you won’t see an error panel telling the user it’s already in there. That was what they wanted anyway.

So, what’s the point?

Short and simple: avoid alerts, if you can.

They disrupt the flow of the app and take the user away from what they’re currently doing. There are many better ways to let the user know something happened – especially if it’s positive feedback.

[twitter-follow screen_name=’eternalstorms’ show_count=’yes’]

Read more