Monochrome

Posted: May 25th, 2012 | Author: | Filed under: Games | No Comments »

Monochrome

An engine test for a new game engine me, Remi Bernotavicius and Roman Duffrene are developing.  It is a story-driven, side-scrolling, puzzling game engine.  More to come, and hopefully a full title in the future!

 

It is a very short story about someone who, in the wake of his grandfather’s death, goes to collect his things, only to find his cousin has gotten there first, and doesn’t have any intention of sharing his inheritance…..

 

UPDATE: It seems the mac version is not working due to some linking errors, I am currently working on a fix

Download Mac Intel

Download Windows


Simple Selectable Toolbar Class

Posted: January 14th, 2011 | Author: | Filed under: Cocoa, OS X, Programming | No Comments »

In many Cocoa applications you may see a very similar layout for the preferences window. It involves a selectable toolbar, but very inconveniently, Interface Builder does not provide a built-in way to create such a toolbar. Until just recently, I was using BWToolkit to create such a toolbar, but in the newest version of Interface Builder, it seems to be broken (version 3.2.5 as of writing). So here is a quick solution I came up with, that tries to use as little code as possible. The only code is a small class (only two methods) called SelectableToolbar. Download it here

Include the class in your project, then create a new window in Interface Builder. Add a NSToolbar to the window, and set the toolbar’s class to SelectableToolbar.
Remove the default items from the toolbar and add new ones, being sure to set them as ‘Selectable’, and set their action to the change: method in the SelectableToolbar
In the window, add a tab view, and make the number of tabs equal to the number of items in your toolbar, and set the tabs to be at the bottom. Set your new tab view to resize with the window, position it in the top left corner and make it fill the whole window, also connect the SelectableToolbar’s tabview outlet to it. Now, populate your tab view’s tabs with appropriate controls and whatnot. When you finish a tab, select all its contents, and choose Layout > Embed Objects In > Custom View. This puts the contents of the tab in its own view, that the SelectableToolbar will use to determine the size of the window. So position the view in the top left corner, and change it’s autosizing so that it stays in the top left corner.

Completed Window (View from Interface Builder)

Keep in mind that, the size of the tab view and of the window doesn’t matter, so you can change it to help you lay things out, just keep the tab view in the top left corner. If you’ve set it up correctly, it should look something like to the right in Interface Builder
Download the Sample Project


Compiling Pdftk for Snow Leopard

Posted: September 20th, 2010 | Author: | Filed under: OS X | 1 Comment »

I decided to look into different types of PDF software hoping to find some awesome PDF utility from linux that would be equally as awesome when I ran it on OS X.  Eventually I came across Pdftk.  It was a command-line utility that was based on a pdf libraries written in Java.  It seemed very interesting, and I couldn’t wait to try it out.  So I fired up good ol’ macports and ‘sudo port install pdftk’ and…

.../usr/bin/ranlib: file: .libs/libgfortran.a(_dim_r16.o) has no symbols
/usr/bin/ranlib: file: .libs/libgfortran.a(_atan2_r16.o) has no symbols
/usr/bin/ranlib: file: .libs/libgfortran.a(_mod_r16.o) has no symbols
creating libgfortran.la
(cd .libs && rm -f libgfortran.la && ln -s ../libgfortran.la libgfortran.la)
make: *** [all] Error 2

arghh.. It fails to build gcc42 which is need for GCJ (A handy part of GCC that turns java class files into native machine code).  It seems to make sense that this utility would need it, being based on libraries written in Java? Okay, so I’ll just download GCC (it includes GCJ) and compile it myself.  I subversion’ed myself the newest copy of GCC’s source

svn checkout svn://gcc.gnu.org/svn/gcc/trunk gcc

I configured it to tell it where all my libraries were and where to install to (for me since I use macports this would be /opt/local), but not before installing its dependencies (libiconv, and mpfr), luckily these installed fine using macports. Then I ran make and waited…and waited..and waited for almost 3 HOURS!. sheesh. Apparently compilers are complicated or something. Anyway.. it was time to remember what I was doing and download Pdftk’s source.  I configured it to the correct paths once again, (so it can find the libraries it needs for GCJ and so forth).  I’m ready to make… and

gcj: error trying to exec 'ecj1': execvp: No such file or directory

What?? Okay after some googling I find out that actually GCJ doesn’t do the actual compiling of the java files into class files, it relies on some jar from eclipse that you can download the latest one here (warning ftp site) (Another pitfall here is that when downloading jar files your browser might append a .zip on the end, just delete the .zip, don’t try to unzip the file).  You can place that file anywhere (I put it in /opt/local/share/gcc-4.6.0/ and renamed it ecj.jar for simplicities sake).  It also needs a script called ecj1 with the contents as follows:

#!/bin/sh
gij -cp /opt/local/share/gcc-4.6.0/ecj.jar org.eclipse.jdt.internal.compiler.batch.GCCMain ${1+"$@"}

Of course change the path in the script to point to your ecj.jar file.  I put this script in /opt/local/bin, but you can put it in any folder in your PATH.  Okay now, back to pdftk…but things still aren’t going well.  Another make, although goes further, reveals that there is a problem with the makefile’s calling of gcjh, aww man.  Okay more googling produces a patch for this problem. I apply the patch with “patch -p0 < patch-filename”.  The patch doesn’t apply without errors of course.  I had to fix these manually, which isn’t too difficult, you just look at the .rej files and you can understand fairly easily the change they are indicating, if not read up on patch files a bit. Okay so things are looking good now, another make and the thing builds all the way to the end…. almost.

multiple definition of `java resource .dummy'

It fails to link all the compiled files together…  Argh… Okay so at least this is a know bug so there must be a fix right?  Well there is a temporary fix, that is to use the objcopy command from binutils to force the dummy resource to be local, but alas objcopy doesn’t seem to work on OS X, I even built it from the newest version of the source and it still doesn’t work.  The only way I found to fix this was to use a hex or text editor to rename the dummy resource.  That’s exactly what I ended up doing after failing to write a script to do it (all of the scripts I wrote ended up corrupting the file somehow).  I opened up all the .o files in the project with smultron and did a find and replace on each one (find: dummy replace: random 5-character string).  This is not the desired way of doing this since there are literally hundreds of them (I may be exaggerating).

Holy crap, that was a lot of work to compile pdftk.  If you’re planning to do the same I sympathise with you, (and let me know if you need any help since I’ve already done it.)  Although, for those of you out there with a 64-bit snow leopard system you can download this package I made of my binaries.  (they install to /usr/local/).  
Download the Package

I hope this helps someone not go through the same frustration I did.  If you have any issues with the package or compiling it.  Let me know I can lend a hand.


Kunugiken Software Release: Pianopub

Posted: September 10th, 2010 | Author: | Filed under: Cocoa, OS X, Site News | 38 Comments »

Pianopub is a Pandora internet radio player.  It lets you manage and listen to your stations in a native Cocoa application.  It is a port of Pianobar, please support these brilliant people.  It has built in support for the apple remote, and the media keys.  It also posts notifications of songs using growl. Listening to Pandora, I felt like I wanted to control it like iTunes, and also I wanted to not have to have my browser open just to listen to it, because I might close it accidentally.  Then when I ran across Pianobar, I was thrilled and delighted, but I just wished it was more user-friendly, and easier to control.  So thats why I made this, so now more people can enjoy the benefits of Pianobar in a convenient package.  Why not check it out yourself, its free! Download Here.  If you like it, or have ideas for new features, let me know about it in the comments.

Pianopub in Action


HowTo: Disappearing NSTable Buttons

Posted: August 10th, 2010 | Author: | Filed under: Cocoa, OS X, Programming | No Comments »
Disappearing NSTable Buttons

Completed Project

Recently I was working on a project where I wanted a certain effect. This was that I wanted the user to be able to delete items out of a table by clicking on the item and not having to add some button somewhere else to do it. So the answer was to put a button on the table to delete it. That was simple enough, just make a table with button cells, but it didn’t look very nice, it showed all the button when you could only delete one at a time. So thus, I decided to make the buttons only appear on the selected table items. Its simple, functional, and you can do it too if you just follow this short guide.

To tackle this problem, there are two “hacks” that we need to do.  First, we have to somehow make the NSButtonCell hide itself.  Next, we have to keep track of which row is selected, and tie that information back to our buttons. To accomplish the first task, will tie the button being hidden to it’s enabled value, since this way is easier then creating a new binding, and it doesn’t matter is the button is disabled if it’s hidden anyway.  Subclass NSButtonCell and override this method with this code.

- (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
{
	if([self isEnabled])
		[super drawWithFrame:cellFrame inView:controlView];
}

In interface builder, drag a NSButtonCell to one of the columns of your NSTableView. (Apple hides it as a ‘Check Box Cell’, see below, you have to change the type to ‘Momentary Push In’).

Interface Builder Check Box Cell (NSButonCell)

Check Box Cell (NSButtonCell)

Setting the Class to HidingButtonCell

Setting the Class to HidingButtonCell

Change the class to your custom subclass. Next we need to somehow get the data in a form we can bind to the button’s enabled key.  There are potentially a couple ways to do this, but I decided to subclass NSTableView, and override this method.

- (void)selectRowIndexes:(NSIndexSet *)indexes byExtendingSelection:(BOOL)extend
{
	[super selectRowIndexes:indexes byExtendingSelection:extend];
	[controller setSelectionIndex:[indexes firstIndex]];
 
	int i;
	for(i = 0; i &lt; [[controller arrangedObjects] count]; i++)
	{
		[[[controller arrangedObjects] objectAtIndex:i] setObject:
			[NSNumber numberWithInt:[indexes firstIndex] == i] forKey:@"enabled"];
	}
 
}

Of, course this way of doing this assumes you’re binding to an NSArray of NSMutableDictionaries.  Next, back in Interface Builder we can bind the column to the new data that’s going to be generated with that method. And thats it enjoy you’re disappearing buttons.  If you want the button to delete the row, like mine, just connect the NSButtonCell’s action to the NSArrayController’s remove: method. If I made any mistakes, or made anything unclear, please leave a comment.  For a closer look, Download the Xcode Project


Remi’s Chat App

Posted: July 18th, 2010 | Author: | Filed under: Cocoa, iPhone, Programming | No Comments »

As promised, here is some example code for the iPhone using ThoMoNetworking. I call it Remi’s Chat App. The mobile companion to Remi’s Chat Program.


Sorry it took me so long to put it up.  Some things to note: It interfaces with Remi’s Chat Program in everything except that iOS doesn’t support the rich text.  You may notice if you download the project that I created a file called NSPatches, this was to allow for the iOS to properly unarchive some classes that it doesn’t have, most notably NSFont.  Other then that, from what I can tell ThoMoNetworking works flawlessly on iOS.  The only thing I couldn’t test was from iOS to iOS, since I lacked two iOS devices, but from iOS to OS X worked great, so I would assume it would work fine.  So here is the bulk of the code for you to peruse, and you can download the project underneath, enjoy!

P.S. Let me know if anybody runs into any issues with the code, I may be able to resolve them easily, since some crashes might just be due to iOS not having certain clases that OS X has, which a simple appending to the NSPatches file should fix.

//
//  Remi_s_Chat_AppViewController.m
//  Remi's Chat App
//
//  Created by Remi Bernotavicius on 7/18/10.
//  Copyright __MyCompanyName__ 2010. All rights reserved.
//
 
#import "Remi_s_Chat_AppViewController.h"
 
@implementation Remi_s_Chat_AppViewController
 
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        // Custom initialization
    }
    return self;
}
*/
 
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
 
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
 
	myServer = [[ThoMoServerStub alloc] initWithProtocolIdentifier:@"remischat"];
	[myServer setDelegate:self];
	[myServer start];
 
	myClient = [[ThoMoClientStub alloc] initWithProtocolIdentifier:@"remischat"];
	[myClient setDelegate:self];
	[myClient start];
 
	[[UIApplication sharedApplication] setDelegate:self];
}
 
- (void)applicationWillTerminate:(UIApplication *)application
{
	NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" disconnected"]] autorelease];
	[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
	[myServer sendToAllClients:temp];
}
 
- (void)server:(ThoMoServerStub *)theServer acceptedConnectionFromClient:(NSString *)aClientIdString;
{
	NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" connected"]] autorelease];
	[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
	[myServer send:temp toClient:aClientIdString];
}
 
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
 
- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
 
	// Release any cached data, images, etc that aren't in use.
}
 
- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}
 
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
	CGRect newFrame = self.view.frame;
	if ([[UIApplication sharedApplication] statusBarOrientation]== UIInterfaceOrientationPortrait
		|| [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown)
		newFrame.size.height -= 216;
	else
		newFrame.size.height -= 162;
 
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3];
 
    [self.view setFrame:newFrame];
 
    [UIView commitAnimations];
}
 
-(IBAction)sendMessage:(id)sender
{
	NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@": "]] autorelease];
	[temp appendAttributedString:[[[NSMutableAttributedString alloc] initWithString:toSend.text] autorelease]];
	[temp appendAttributedString:[[[NSMutableAttributedString alloc] initWithString:@"\n"] autorelease]];
 
	[myServer sendToAllClients:temp];
	toSend.text = @"";
}
 
- (void)textFieldDidEndEditing:(UITextField *)textField
{
	CGRect newFrame = self.view.frame;
	if ([[UIApplication sharedApplication] statusBarOrientation]== UIInterfaceOrientationPortrait
		|| [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown)
		newFrame.size.height += 216;
	else
		newFrame.size.height += 162;
 
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3];
 
    [self.view setFrame:newFrame];
 
    [UIView commitAnimations];
}
 
-(void)server:(ThoMoServerStub *)theServer didReceiveData:(id)theData fromClient:(NSString *)aClientIdString {}
 
-(void)client:(ThoMoClientStub *)theClient didReceiveData:(id)theData fromServer:(NSString *)aServerIdString;
{
	NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithAttributedString:theData] autorelease];
	history.text = [history.text stringByAppendingString:[temp string]];
 
	[history scrollRangeToVisible:NSMakeRange([history.text length]-2, 1)];
}
 
- (void)dealloc {
    [super dealloc];
}
 
@end

Download the Xcode Project


ThoMoNetworking Framework

Posted: June 8th, 2010 | Author: | Filed under: Cocoa, Programming | 2 Comments »

I happened to stumble upon an amazing framework called ThoMoNetworking. It takes the complicated task of networking in Cocoa and makes it extremely easy. Basically it lets you define your own protocol and connects to other instances of it on the network automatically using bonjour. Then to send data it allows you to send objects. The potential from this framework is huge, especially since it works on both iPhone OS and Mac OS.  It is incredibly simple, check out their website for how to use it, it is outlined in its full simplistic beauty.

With such a powerful framework at my disposal, I decided to test it out.  I wanted to see just how easy it would be to create my own ad-hoc chatting program.  I’ve included the source as well so you can test out the framework for yourselves.

I give you, Remi’s Chat Program

Remi's Chat Program

Since ThoMoNetworking lets you send any object, I was able to send NSAttributedString objects, so the text’s color and font are preserved.  I was also able to include recalling previously sent messages with the arrow keys (like in the terminal) and growl support as a superfluous features.  This seemingly complicated program is actually very little code.

//
//  Remi_s_Chat_ProgramAppDelegate.m
//  Remi's Chat Program
//
//  Created by Remi Bernotavicius on 6/1/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//
 
#import "Remi_s_Chat_ProgramAppDelegate.h"
 
@implementation Remi_s_Chat_ProgramAppDelegate
 
- (NSDictionary *) registrationDictionaryForGrowl {
	NSArray *array = [NSArray arrayWithObjects:@"new message", nil];
    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
                          [NSNumber numberWithInt:1],
                          @"TicketVersion",
                          array,
                          @"AllNotifications",
                          array,
                          @"DefaultNotifications",
                          nil];
    return dict;
}
 
-(void) growlAlert:(NSString *)message title:(NSString *)title{
    [GrowlApplicationBridge notifyWithTitle:title
								description:message
						   notificationName:@"new message"
								   iconData:[[[NSApplication sharedApplication] applicationIconImage] TIFFRepresentation]
								   priority:0
								   isSticky:NO
							   clickContext:@"bringFrontContext"];
}
 
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
	[GrowlApplicationBridge setGrowlDelegate:self];
 
	myServer = [[ThoMoServerStub alloc] initWithProtocolIdentifier:@"remischat"];
	[myServer setDelegate:self];
	[myServer start];
 
	myClient = [[ThoMoClientStub alloc] initWithProtocolIdentifier:@"remischat"];
	[myClient setDelegate:self];
	[myClient start];
 
	[[NSApplication sharedApplication] setDelegate:self];
	previousChats = [[NSMutableArray alloc] init];
	current = 0;
}
 
- (void)server:(ThoMoServerStub *)theServer acceptedConnectionFromClient:(NSString *)aClientIdString;
{
	NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" connected"]] autorelease];
	[temp addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSFont boldSystemFontOfSize:12], NSFontAttributeName, nil] range:NSMakeRange(0, [temp length])];
	[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
	[myServer send:temp toClient:aClientIdString];
}
 
-(void)dealloc
{
	[previousChats release];
	[super dealloc];
}
 
-(void)retreat
{
	if(current &lt; [previousChats count]) 	{ 		current++; 		[[toSend textStorage] setAttributedString:[previousChats objectAtIndex:current]]; 		if(current == [previousChats count]-1) 			[previousChats removeLastObject]; 	} } -(void)advance { 	 	if(current &gt; 0 &amp;&amp; [previousChats count] &gt; 0)
	{
		if(current &gt; [previousChats count]-1)
			[previousChats addObject:[[toSend attributedString] copy]];
		current--;
		[[toSend textStorage] setAttributedString:[previousChats objectAtIndex:current]];
	}
}
 
- (void)windowDidBecomeKey:(NSNotification *)notification
{
	[mainWindow makeFirstResponder:[toSend superview]];
}
 
-(IBAction)sendMessage:(id)sender
{
	NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@": "]] autorelease];
	[temp appendAttributedString:[toSend attributedString]];
 
	[previousChats addObject:[toSend attributedString]];
 
	if ([previousChats count] &lt;= 10)
		current = [previousChats count];
	else
		[previousChats removeObjectAtIndex:0];
 
	NSString* t = [temp string];
	if(![[t substringWithRange:NSMakeRange([t length]-1, 1)] isEqual:@"\n"])
		[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
	[myServer sendToAllClients:temp];
	[[toSend textStorage] setAttributedString:[[[NSAttributedString alloc] initWithString:@""] autorelease]];
}
 
- (void) growlNotificationWasClicked:(id)clickContext{
	[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
 
}
 
-(void)server:(ThoMoServerStub *)theServer didReceiveData:(id)theData fromClient:(NSString *)aClientIdString {}
 
-(void)client:(ThoMoClientStub *)theClient didReceiveData:(id)theData fromServer:(NSString *)aServerIdString;
{
	NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithAttributedString:[history attributedString]] autorelease];
	[temp appendAttributedString:theData];
	[[history textStorage] setAttributedString:temp];
 
	[history scrollRangeToVisible:NSMakeRange([[history textStorage] length], 0)];
 
	if(![mainWindow isKeyWindow])
	{
		[[NSApplication sharedApplication] requestUserAttention:NSCriticalRequest];
		[self growlAlert:[(NSAttributedString*)theData string] title:@"New Message"];
	}
}
 
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
	NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" disconnected"]] autorelease];
	[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
	[temp addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSFont boldSystemFontOfSize:12], NSFontAttributeName, nil] range:NSMakeRange(0, [temp length])];
	[myServer sendToAllClients:temp];
 
	return NSTerminateNow;
}
 
@end

Download the Xcode Project

Let me know if there are any issues with the source, or if you would like to see more, like an iPhone OS example, just post a comment.


New From Kunugiken WikiTyper

Posted: May 15th, 2010 | Author: | Filed under: Cocoa, OS X, Programming | No Comments »

I was playing the fabulous typing game TypeRacer when I thought that it would be fun to type some sort of other text. I decided to try making my own typing program. So I threw together this new typing game for OS X that lets you type random paragraphs of text from wikipedia. Its absolutely free, try downloading it here Download Page.

WikiTyper in Action

If you have any comments on the game please post them below. Some things I know are not working and I might fix in the future if people ask about them.  The words per minute is actual words per minute not the correct wpm, (if anyone knows the formula?)  Also occasionally it will display characters that you cannot type, but I couldn’t find a way to remedy that efficiently.  Finally, for those of you Linux and Windows users, a Java port is being made by someone else.  I will post a link if/when it is finished.


Cocoa: Making Properties KVO Compliant

Posted: November 14th, 2009 | Author: | Filed under: Cocoa, Programming | 1 Comment »

In Cocoa KVO or Key-Value-Observing compliant means that the value of a certain object sends notifications out when its value has been changed to an observer. An example would be values stored in a NSMutableDictionary or NSMutableArray. Since they are KVO compliant, you can bind something to a value in one of these objects, and will be updated automatically, no glue code required. Although not all objects have their values KVO compliant and this can cause problems for example when trying to bind to them in Interface Builder. A good example can be seen with NSDocument’s documentName. Notice you can bind an object’s value to documentName, but if the documentName changes, this value does not update. The way to fix this, is to subclass NSDocument and send out notifications whenever documentName is changed. A class-dump of NSDocument reveals the -(BOOL)_setDocumentName:(NSString*)name method. All you have to do is add this method to your NSDocument subclass

-(void)_setDisplayName:(NSString*)name
{
	//Hack Display Name to make KVO Compliant
	[self willChangeValueForKey:@"displayName"];
	[(YourClassNameHere*)super _setDisplayName:name];
	[self didChangeValueForKey:@"displayName"];
}

And that should be it. Note: I changed the method’s return type to void because otherwise it will create an error in the console about KVO compliant methods not being able to return anything other then void.

Also note that this is for read-only binding, to do a binding where you can change the value you have to implement and expose a new binding programmatically.

Apple’s Documentation on KVO


Fixing Old Printer Drivers to Work in Snow Leopard

Posted: September 3rd, 2009 | Author: | Filed under: OS X, Personal | 24 Comments »

The upgrade to snow leopard may be leaving some of you with not working printers. When I upgraded I could no longer print to my Xerox Workcentre Pro 238. The thing it seems is that snow leopard deletes all of your old PPDs and printer drivers. I had to download and install the driver again. Then alas, after doing so, the printer failed to function, it gave me the error message “The printer software was installed incorrectly. Please reinstall the printer’s software or contact the manufacturer for assistance.”

After researching the error, I came to the conclusion that it has to do with snow leopard upgrading CUPS. The newest version of CUPS, I read, requires that all the drivers’ files be owned by root. After investigating I found that Xerox’s PPD’s and plugins were NOT owned by root and thus causing the problem. To remedy this problem just type this command into the terminal:

sudo chown -R root:admin /Library/Printers

(The command might take a while to run.) This owns the /Library/Printers folder and everything in it to root, this could potentially fix many different printer software to work with snow leopard since it can effect pretty much any printer driver. So if you’re having problems try giving this a shot. Good luck.