How-To: ‘Gray out’ Files in Finder

When copying files in Finder, you might have noticed that the newly created, still-being-written-to files are ‘grayed out’, conveniently informing the user that the file is not ready yet.

Greyed out files in Finder

I wanted to replicate that for an upcoming upgrade of Transloader (along with a progress indicator, as you can see in the screenshot above, but that’s another topic), and after trying a couple of things, I found out how to do it.

I tested this on macOS High Sierra only, since it’s the OS version I’m targeting right now, but I don’t see a reason why it wouldn’t work on earlier versions of macOS.

It’s All in the Date

After digging around on the internet, I found that all that needs to be done is to change the file’s creation- and modification dates to one specific date, namely:
January 24th, 1984, 09:00:00 AM

Setting the creation and modification dates of the file to be greyed out

And it works great – the created file appears ‘grayed out’ in Finder.

There’s a downside, however:
When copying a file in Finder, and trying to move that still-being-written-to file, Finder will display a convenient message that tells the user the file is in use and moving it might cause problems.
This doesn’t happen when using this date-setting approach.

So I kept digging.

The Solution

What I did, then, was use Terminal and the ‘mdls’ command to list the meta data of the still-being-written-to file:

mdls in Terminal on a copying file

At first, coming from the date-approach, I noticed the kMDItemFSCreationDate item, stating
1904-01-01 00:00:00 +0000

However, setting that as the creation date does nothing at all.

Then, I noticed the kMDItemFSCreatorCode and kMDItemFSTypeCode fields (red arrows in the screenshot of Terminal above).

Setting those like this…

Setting creator and type codes in Objective-C

…does exactly what I wanted – it ‘grays out’ the file in Finder, and displays the convenient Finder error message when trying to move it:

Finder error message when trying to move a still being written to file

Mission accomplished – we’re done!

Please keep in mind, though, that the user may still choose “Continue” to move the file, so you should definitely use an NSFileCoordinator to take care of that.

How To: Animate a determinate NSProgressIndicator (Open Source)

I’m not sure if I’m imagining things, but I believe at some point before OS X Yosemite, a determinate NSProgressIndicator was able to animate to its new doubleValue, not just “jump” to it.

In an effort to have that animation again, I wrote a little category on NSProgressIndicator that does exactly that, using NSAnimation.

Progress bar animation using ESSProgressIndicatorCategory

NSProgressIndicator and Animation

NSProgressIndicator has a method called -startAnimation:. However, as the documentation states, this has no effect on determinate progress indicators.
Calling progressIndicator.animator.doubleValue = 5.0; doesn’t animate either. So with options that come with the class, we’re stuck.

As I try not to reinvent the wheel for something that’s already solved, I did some googling around, but that didn’t yield any results, either.
What became clear, though, was that there’s a lot of confusion about what -startAnimation: actually does.

NSProgressIndicator+ESSProgressIndicatorCategory

Not finding a solution on the internet, I decided to write my own, as I figured it wouldn’t take a lot of time (it didn’t).

I definitely didn’t want to subclass NSProgressIndicator and override any drawing methods.
That would have a) taken an unjustified amount of time and b) been a huge pain in the neck for sure.

The solution to me then was to use NSAnimation.

The goal was to have one method to call that sets the new doubleValue and animates to it nicely:

New method to animate a progress indicator's doubleValueThe category’s – (void)animateToDoubleValue: method

It calls a subclass of NSAnimation named ESSProgressBarAnimation with the new value and starts the animation.

initialization of the NSAnimation subclassInitializing the NSAnimation subclass ESSProgressBarAnimation

We save the original doubleValue of the progressindicator, set the duration and animationCurve and set the animation’s animationBlockingMode to NSAnimationNonBlockingThreaded so that when there’s a mouse event, for example, the animation doesn’t stop.

NSAnimation's setCurrentProgress method

When an NSAnimation object’s -startAnimation method is called, it automatically calls -setCurrentProgress: on itself until currentProgress is 1.0, meaning the animation has ended (currentProgress ranges from 0.0 to 1.0). The value is based on the duration and the animationCurve.
In this overridden method, we calculate the delta between the new and the initial doubleValue of the progressIndicator, multiply it by currentProgress and send it to the progressIndicator. That’s it.

How To Use NSProgressIndicator+ESSProgressIndicatorCategory

Add the category’s .h and .m files to your project, import it where you need it and update your progress indicator’s doubleValue by calling -animateToDoubleValue: with the doubleValue you desire to animate to.

The Source Code

The repository (a sample OS X app) is available on Github.

It was developed (and tested) on OS X Yosemite 10.10.3 using Xcode 6.3.1 but should work on earlier versions of the operating system.

More source code is available here (or directly on my github profile page) if you’re interested. If you have any questions or feedback regarding my open source projects, please be sure to mail or tweet me – I’m looking forward to your feedback!

Enjoy!

Making ZEN (Part 2)

First Concept of ZENFirst concept of ZEN

After last week’s guest blog post by my cousin Sebastian about how he came up with the idea of the iOS game ZEN, the design and conception process behind it and the soundtrack, today it’s my turn to talk about putting it in code and making it all come to life.

The Premise

Like a lot of developers I know, I became intrigued with programming because of games. As a kid, I always wanted to develop games for a living, make the next Diablo. So of course I jumped at the idea of creating a game when my cousin asked me if I was interested.

I had never actually programmed a game before, so when Sebastian approached me about developing a game with him, I was already seeing myself having to learn OpenGL and everything that comes with it.

Luckily, it soon became clear that it would be a 2D game, almost 8-bit-ish, like an old Super Mario Bros game. So my fears of having to learn something new* were put to rest and the more he told me about the game, the more I realized that Core Animation would be the perfect fit for this project.

The game is about a cube with random numbers on it. Your goal is to reach ten with these numbers by turning the cube and selecting the appropriate sides within ten seconds.

ZEN Cube Animation

*just kidding, I love learning new stuff, but for a side-project having to learn OpenGL would have been a little much, especially with all my other apps that need constant attention

Core Animation actually was pretty much made for this kind of stuff. Even if the game had had some 3D effects (for example, some sort of perspective distortion when turning the cube, etc), it would have been fairly easy to implement.

First Blood

The first thing I did in the process of developing ZEN was to prototype the cube itself. I began by mapping out the cube because a) I didn’t have one handy and b) to get a visual on each side:

Mapping out the cube

Because I was using Core Animation and it was all in 2D space, I had to figure out what side would go where when the cube was turned from left to right, right to left, from the top or the bottom, so that the numbers would stay on the same side and not end up any place they shouldn’t be. I went so far to write down which side would go where once the cube was turned in any direction

Mapping out which cube side would go whereWhich side goes where when turning the cube?

To make the animation possible, I would have to use at least two CALayers that changed in shape and color, and would have to be kept up to date in terms of data (which side holds which number).

One layer would always be hidden, the layer to turn to, so to speak, the other layer would always be visible. They would alternate in doing that.
For example:

Layer 1 is visible with the front number of the cube.
You turn the cube right and layer 2 (still hidden) gets the number of the left side of the cube.
Layer 1 is animated to fold to the right
Layer 2 shows and animates to the full size of the front cube side.
Layer 1 is hidden

Turning Cube Down on PaperTurning the cube from the top on paper

With that done, I had the cube – of course, there were some kinks to be worked out (for example, sometimes the hidden layer would suddenly be visible with a completely wrong size), but basically, the cube was working.
In code, turning the cube upwards looks like this:

- (void)turnUp
{
ESSCubeSide *oldUp = self.topSide;
ESSCubeSide *oldFront = self.frontSide;
ESSCubeSide *oldDown = self.bottomSide;
ESSCubeSide *oldBack = self.backSide;
self._cubeDict[ESSCUBE_FRONT] = oldDown;
self._cubeDict[ESSCUBE_TOP] = oldFront;
self._cubeDict[ESSCUBE_BACK] = oldUp;
self._cubeDict[ESSCUBE_BOTTOM] = oldBack;
}

This is only the data model, of course. The view code just the two layers – resizing them in unison, hiding one layer and showing the other, etc.

Random Numbers

The next thing that had to be done was to fill the cube with random numbers, some of which would add up to ten.

I chose to do the following:

  1. Decide how many sides it takes to solve the current cube (a number between 2 and 6); let’s say it’s 3 – 3 sides to solve the cube.
  2. Loop while we create 3 random numbers between 1 and 9 that add up to ten.
  3. Fill the rest of the cube (3 more sides) with random numbers between 1 and 9.
  4. Shuffle the resulting array of six numbers so the solving sides aren’t always on the same sides
The same principle works for the minus mode, where there are positive and negative integers that you need to select to add up to ten.

Interface

The first interface concept, as you can see in the first screenshot of this blog post, was pretty simple. The title and three buttons. There was no mention of animations!

As it always happens, things change during the development process, you iterate on everything, and the interface gets overhauled as well. This new one was, in my opinion, much nicer as it demonstrates the “cube-y” nature of the game very nicely.

ZEN Line animation

But it took me some time to get there. I was hoping that Sebastian could define the animations in svg or gif or something like that and I could just load them in and display them.
However, I could not do that – apparently iOS doesn’t support svgs or gifs out of the box (and I didn’t want to rely on 3rd party libraries to do the job). After googling around for a couple of days (because, you know, you want to be thorough), I tried doing it in a web view, because these animations would work in the browser. However, I wouldn’t have that amount of control over them as I did with the final approach I took – code it in Core Animation as well.

So I have one view class that, depending on the width and height of the bounds of the view either expands horizontally or vertically. That was the easy part.

The hard part was creating all the views in Xcode’s Interface Builder with the proper dimensions and positioning them so they would define the buttons and letters. I’m just glad the Help – view is not animated 😉 :

Help ViewThe Help View – thankfully for me, not animated

Creating ZEN was a very exciting experience and I learned a lot during the process. As I usually work alone, working within a team on this project (even if it’s just two people) was a breath of fresh air and is a lot of fun, bouncing ideas off of each other, inspiring each other – there’s a whole lot of energy there.
While I do have a few dear friends with whom I can exchange ideas over the internet for my own projects, it’s quite different when you’re one on one, face to face.

It’s been  a lot of fun.

—-
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.