source code

For Transloader’s upcoming version 3.0, I needed an NSMenuItem that not only showed a title, but also a subtitle, along with an optional image.

Because it took a bit of work and “reverse-engineering” (the click-on-an-item-selection-animation’s timing, in particular), I figured someone else might benefit from this.

Where to get it / Sample Project

It’s all pretty straight forward, and best shown / explained as an Xcode project, which you can download on Github.
This is basically all you need to do:

Screenshot the sample project's source code

That’s it!

Caveats

There are some things this implementation can not do, which the default NSMenuItem can:

  • There is no type select
  • The arrow keys can’t be used to go through the items
  • You can’t activate items with the space or enter keys

Basically, keyboard interaction is unavailable.

I do hope it’s useful to you anyways.
If you’re using this, I’d love to hear from you! 😊

Read more

Since I’ve had to go re-watch WWDC20’s “Adopt the New Look of macOS” session (at around the 07:03 mark), I thought I’d note it down here – for anyone else late to the update-for-macOS-Big-Sur-game 😉

What we want to achieve is go from this UI (basically standard on any macOS before Big Sur):

Screenshot of Yoink's preferences on macOS Catalina and earlier

to this UI (new UI for Preferences windows on macOS Big Sur):

Screenshot of Yoink's Preferences on macOS Big Sur

And it’s fairly easy to do so. All you need to call is (pardon the Objective-C, Yoink for Mac (and iPad and iPhone, for that matter), is still 100% Swift-free..)

self.window.toolbarStyle = NSWindowToolbarStylePreference;

and update your toolbar items’ icons, and you’re all set.

Screenshot of Xcode  24 09 2020 08 48 22

 

 

– Matthias
mail | website | twitter | instagram | facebook

Read more

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.

Read more

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!

Read more