If I may put my geek hat on… this is full of win on multiple levels:
Programming
Licenses
In the world of software, licenses are a big deal. There’s the pure legal aspect, there’s the liability aspect, there’s protection for property, and then there’s a lot of philosophy that goes into licenses.
For instance, consider the Open Source licenses. They are there for legal purposes, but also to promote a specific philosophy about how source code should be treated.
Well, in their latest attention-whoring effort, PETA has created a flavor of an open source license. I’m not going to link to it to give them any more attention than this post getting indexed by Google and Bing will give it. But the idea is they took a BSD-style license as a foundation then added a clause that use of the software cannot be used to harm humans or animals. Because of that, the license actually doesn’t satisfy the definition of an open license, because an open license strives to minimize restrictions and promote openness — this license discriminates against that, but PETA openly acknowledges that (because their point isn’t openness, it’s driving home their narrow viewpoint).
So as a wonderful alternative, we have the WTFPL — Do What The Fuck You Want To Public License.
Reproduced here in its entirety:
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION0. You just DO WHAT THE FUCK YOU WANT TO.
Fast Enumeration is awesome
Fast Enumeration, a facet of the Objective-C 2.0 language, is awesome.
I’m finally working on a project where Mac OS X 10.5 is the minimum, so I can start using more “modern” conveniences. And boy, being able to write:
for (id obj in container) {
[obj doSomething];
}
instead of:
NSEnumerator* containerEnumerator = [container objectEnumerator];
id obj = nil;
while ((obj = [containerEnumerator nextObject])) {
[obj doSomething];
}
is just awesome. I know it seems small, but when you type tons of code in a day, such simplicity in code is fantastic.
IKImageView is… odd
Apple made a really cool thing in Image Kit and IKImageView. It’s an amazing amount of power in very easy-to-use drop-in components.
Or so you would think.
I spent the weekend battling with IKImageView, and I’m still not getting exactly what I want.
Right now, it’s a matter of scrolling behavior. Take a look at how the Preview.app works. In general, it opens up an image such that the image is autosized to fill the window, keeping the image’s aspect ratio intact. If you resize the window larger or smaller, the image resizes accordingly, again maintaining the aspect ratio. Note however that scrollbars never show up. In general, this is good because it shows the whole of the image, even if it’s scaling down the image’s size, because most people want to view the whole image, not just part and then having to scroll around. But, if you do want to scroll around you can. You can use a function such as “zoom in” to get closer to the image, which should then make scrollbars appear (if the sizes are right), and you scroll from there. It works out great in Preview.app.
I wonder if Apple uses IKImageView in Preview.app or not, because I can’t get the same behavior.
But then I noticed something.
In the few bits of sample code there are about using IKImageView, the nib/xib file doesn’t actually embed an IKImageView within it. It has an NSScrollView then within that is merely an NSView. But in editing the NSView within the nib it gets a “custom class” setting typed in of IKImageView. So I tried that, because why was it working in demos but not in my app? So, mirror what you see in the working copy.
Things work.
Say what?
So I even try it in the demo app. Change the NSView to an IKImageView, rebuild. Things no longer work.
Holy crap.
So I try it in my app, using an NSView, changing the type to IKImageView. And lo… it works. It’s not 100%, some of the functions like “size to fit” aren’t calculating the numbers perfectly, but it’s a heck of a lot better.
Then I figured to try building it all by-hand in code instead of nib/xib files. I can’t get that to work. The app constantly crashes on me. As I isolate it down, it’s something about IKImageView.
Go figure.
I’ll work on filing bugs with Apple about this. None of it makes sense, and it’s damn frustrating. But there’s so little information out there about using IKImageView it makes it even more frustrating. So much power, so much potential, and it just falls flat. 😦
Updated: OK, color me really confused now.
I started to write up a bug report for Apple, using Apple sample code as a basis to demonstrate the problem. Sure enough, I was able to demonstrate some of the problems, such as IKImageView not being playing well with autohiding scrollers. But the other problems I was seeing, I now couldn’t get them to reproduce.
Eh?
So I went back into my app, gutted things, and started from scratch.
Now it works.
Eh?
Granted, there are still some bugs and problems with IKImageView itself, but now that it’s working is very strange. I did add some workarounds for issues (e.g. I just don’t auto-hide scrollers, I subclassed and added an -isFlipped override.), but man… very strange. I did note that at one point InterfaceBuilder fired an internal assertion failure, so something was out of whack for sure. Maybe the xib was corrupted somehow in all of this? Who knows.
Still, IKImageView is really awesome, I just look forward to all the kinks being ironed out.
Floating-Point for the Common Man
When does 0.1 + 0.2 not equal 0.3? When you’re dealing with floating-point arithmetic.
Floating-point math is a complex thing to grok, but it’s important if you’re a programmer. Unfortunately, a lot of the explanations of this concept are obtuse and make your eyes glaze over. But here’s a fantastic guide that explains the important bits but in a way that everyone should be able to understand.
Here’s why there’s no Flash on the iPhone/iPad/iPod
This is a detailed letter from Steve Jobs as to why Flash isn’t on the iPhone/iPad/iPod.
You really need to read the article to get all the details, but briefly:
- Flash is a closed system. Yes Apple admits to some level of being closed, but HTML5, CSS, JavaScript are open standards.
- The “full web”
- Reliabilty, security, and performance. Flash fails in all 3 areas.
- Battery life. Flash drains it heavily and quickly.
- Touch interfaces. Flash isn’t designed for that.
- Inserting a third-party into the user experience can yield less than optimal results.
Speaking as not only a consumer of these products but also as an Apple Developer for almost two decades, I can say Apple’s reasons are quite sound.
One very telling and modern reason?
Flash was designed for PCs using mice, not for touch screens using fingers. For example, many Flash websites rely on “rollovers”, which pop up menus or other elements when the mouse arrow hovers over a specific spot. Apple’s revolutionary multi-touch interface doesn’t use a mouse, and there is no concept of a rollover. Most Flash websites will need to be rewritten to support touch-based devices. If developers need to rewrite their Flash websites, why not use modern technologies like HTML5, CSS and JavaScript?
This is quite true. Touch-based is where computing is headed, and Flash just doesn’t grok it. So yes, if you need to rewrite, might as well rewrite in more modern technology.
Anyway, instead of whining to get Flash, we should be encouraging web developers to move beyond Flash.
Code Bubbles
For you developers out there, check this out: Code Bubbles.
And you really need to watch it full-screen, high def, as it’s hard to understand what they’re talking about without being able to see the text they’re editing.
Present development IDE’s are all about text files… you are organized based upon the way the data is stored. I recall long ago thinking about how that, well, sucked. 🙂 It’s one way to organize things for sure, but why should we be limited by the storage constraints of the system if that’s not the best way to actually organize and access the data? We should be able to abstract that notion away. Isn’t that part of what computers are all about?
I really like how this “code bubble” approach works to allow you to focus on work. The data is just the data. You work with the data. You can see how the data relates to other data. If you need to add your own data, like a flag or a note, you can do that. How you can preserve data that is generated, such as a debug session, and then come back and revisit that at another time be it just starting a second debug session or something you did weeks ago. How documentation, how bug reporting, how annotations are just integrated into the system and so you can hook all of these things together to allow you to work on a problem with all the necessary parts just right there and connected together. Then how you can take all of this and serialize it to share with a colleague? That’s pretty cool.
I will say, some of the bubbles are a little annoying, mostly because I think the left-to-right hierarchical structure is a bit cumbersome on screen. But that’s a minor nit, and they’ve actually done a fair job at trying to address a lot of that mundane usability minutia. The concepts here are really good, and I figure all it takes is time in use to actually develop and truly refine the workflow. Bubbles may not be the final solution to improving the developer workflow, but it’s great to see someone working to develop a model that rethinks the whole process and strives to improve upon our existing paradigms.
Neat idea.
Buried in treemaps
I realized the day was half-way over and I hadn’t written anything here.
Why?
I’ve been buried in documentation on the concept of treemaps. Lots of reading, studying of code and algorithms. It’s neat stuff.. at least to a geek like me.
I’ll be working on my own implementation soon. For what? Well… just can’t say. 🙂
Is your NSTableView showing 2 tooltips?
Is your NSTableView or NSOutlineView showing 2 tooltips (in Mac OS X 10.5 or later)?
If so, you may be being bit by some well-meaning automagical code. But there’s a simple solution. Read on!
NSRuleEditor – you are so cool but so frustrating
If you’re not a Mac programmer, you can stop reading now. 🙂
Apple has this cool new widget called NSRuleEditor, introduced in Mac OS X 10.5. A lot of the software I’ve written over the past some years involves searching for things and often the user needs to provide you with rules by which to search. I’ve always had to invent my own solutions, and it’s a non-trivial thing to do. So when I finally heard about NSRuleEditor some years ago I was most excited to finally have an OS-provided solution.
The way Apple implement the widget is pretty cool. They realize people will use it to display whatever arbitrary data model they have, so they structured it that way. The NSRuleEditor iself is a single control, the contents of which are opaque to you… mostly. There’s your data model objects, which NSRuleEditor calls your criteria (that bugs me, as “criteria” is plural and the API uses it in a singular sense, but oh well… I can understand why they did that). The criteria can be whatever you want them to be, it doesn’t matter. But each criteria object then has a “display value”, which is how the criteria is displayed and/or worked with in the GUI, such as a string or a menu item or a text field or date picker. Thus I can have a LabelObject, an OperatorObject, and a TextObject which represent my data model. The LabelObject would have a display value of “name” and a predicate value of “left hand expression” and kMDItemDisplayName, the OperatorObject would have a value of “contains” and a predicate operator value of “IN”, and the TextObject would have a display value of an NSTextField and a predicate value of the “right hand expression”. Thus I could get the GUI to display “name contains <foo>” and create a query string like “kMDItemDisplayName IN <foo>”.
It’s a little obtuse to wrap around at first, but once you figure it out, it’s actually pretty well done. Apple has to make a generic control that anyone can use, and rule display/editing is non-trivial. Really, they did a pretty good job with this.
One thing to realize is the displayValues are not necessarily what is displayed in the GUI. Yes they generally are, but when you do this there is no localization. However, NSRuleEditor has a way you can provide a dictionary of formatting strings that allow you to change the displayed format. You see, the criteria objects are truly the data model. The displayValues aren’t truly the view… they can be, but they’re like “one step back” from being the view. Really, you should be using the formatting strings to get the real view… and then it’s like the displayValues are a “view model” for the view. Confusing? I know, but this is how it is. The formatting strings are your way to localize the display, but of course you don’t need to use it for localizing… you could just use them to change what is truly displayed to something other than the strict “view model”. There’s flexibility in the mapping the formatting strings provide.
So for instance I want to do a name criteria. The formatting strings are a key-value pair. The key is a pattern that matches the labels of your criteria objects. For instance:
%[Name]@ %[matches, contains, is, begins with, ends with]@ %@
Provides the formatting key. The %@ groups demarcate special identifiers, so that in your value, you’d have something like:
%1$[Name]@ %2$[matches, contains, is, begins with, ends with]@ %$3@
As the formatting value is parsed, it picks up the “x$” identifiers and knows this affects the ordering of the elements in the string, so you could shuffle things around. As well then, the items within the brackets are also ordered. So for instance if I had a value string like:
%1$[Name]@ %2$[ends with, begins with, is, contains, matches]@ %$3@
then when my data model said “matches” the GUI would present “ends with” to the user. Of course, this would be highly confusing to the user thinking they were doing an “ends with” search but the actual search ended up doing a “matches” search. But it shows what you can do.
Of course, the real benefit of this is localization. Let’s say we were converting “name contains foo” to Japanese. The key is the same as above, but the value then becomes:
%1$[お名前は]@ %$3@ %2$[が入っている]@
Which is “name contains”.
All of this is good and great. But where it falls flat? You have no way to know what NSRuleEditor is displaying. What if you wanted to get that that information? You can’t. You can get the -criteriaForRow: to get the row’s criteria objects. You can get the -displayValuesForRow:, which gets the raw display values. But you can’t get the formatted display values, like a -formattedDisplayValuesForRow:
*sigh*
This put a big crimp in things for me and the code I’m presently working on. Granted, I can get all the elements myself, of the criteria, the display values, and the formatting strings, but to apply the formatting strings to the display values is a non-trivial task. IMHO, a bug/shortcoming in the NSRuleEditor API. Bug filed: rdar://problem/7741182.
NSPredicate trick
That all said, there is a cool NSPredicate trick.
This comes from blacktree-alchemy’s code for QSMDPredicate. It’s basically a way you can shove a MDQuery syntax string into an NSPredicate and have it all work out. Handy because NSRuleEditor is based upon NSPredicate, but since NSPredicate and the MDQuery syntax don’t have a perfect one-to-one correspondence (or maybe you’re using MDQuery instead of NSMetadataQuery), it’s handy.
In case the QSMDPredicate code ever goes away, here it is. Again, this is NOT mine, just someone thankful for it’s existence and release under the Apache License 2.0.
QSMDPredicate.h
//
// QSMDPredicate.h
// QSSpotlightPlugIn
//
// Created by Alcor on 5/6/05.
//
#import
@interface QSMDQueryPredicate : NSPredicate {
NSString *query;
}
+ (id)predicateWithString:(NSString *)aQuery;
- (NSString *)query;
- (void)setQuery:(NSString *)aQuery;
@end
QSMDPredicate.m
//
// QSMDPredicate.m
// QSSpotlightPlugIn
//
// Created by Alcor on 5/6/05.
//
#import "QSMDPredicate.h"
@implementation QSMDQueryPredicate
- (id)generateMetadataDescription{
return query;
}
+ (id)predicateWithString:(NSString *)aQuery{
QSMDQueryPredicate *predicate=[[[self alloc]init]autorelease];
[predicate setQuery:aQuery];
return predicate;
}
- (NSString *)predicateFormat{
return query;
}
- (NSString *)query { return [[query retain] autorelease]; }
- (void)setQuery:(NSString *)aQuery
{
if (query != aQuery) {
[query release];
query = [aQuery copy];
}
}
- (id)copyWithZone:(NSZone *)zone
{
id copy = [[QSMDQueryPredicate allocWithZone:zone]init];
[copy setQuery:[self query]];
return copy;
}
@end
(Wow… I just realized my current WordPress.com theme is crappy at handling blocks. I need to learn more CSS so I can tweak that).