Re: Custom NSFormatter classes
Hello again Patric and others. I have another question related to the previous one. I now have the following things: * Foo model class * FooFormatter class which converts Foo objects into string representations * User interface with NSTableView which uses the FooFormatter in a text field cell What I would like to do next (yet not sure how to do it) is to have a context menu attached to the table view with menu items calling actions on a Foo object underneath the mouse cursor. Lets consider that the Foo class has something like the following: - (IBAction)setOneDot:(id)sender; - (IBAction)setTwoDots:(id)sender; - (IBAction)setThreeDots:(id)sender; And the context menu would have items like One dot, Two dots and Three dots which would call those actions. The problem here is that target-action relationships can't be bound in the Interface Builder, since target is not known until the user presses right mouse on the table view. I am guessing that the best solution would be to subclass NSCell or NSTextFieldCell and then override some method to handle the mouse event? Or maybe this could be done with some sort of Cocoa Bindings trickery to have those menu items call directly on the setDots: method of the Foo class, without having to implement a separate action for each setXXXDot(s) ? How about displaying a checkmark on the menu item for the current state? On Jan 3, 2010, at 1:58 PM, Patrick Mau wrote: Hallo Henri Your assumption about how formatters should work are correct. To provide a useful answer I have setup a mini project here, because I have stumbled over a detail I did not now: http://public.me.com/pmau I took your approach and implemted a minimal datasource and a Foo object. This is not a great example, but here's what II did not know: When you wire up the formatter to the text field cell in IB, setFormatter is called on the TextFieldCell, which in turn will call your formatting code withe the cell's title: run [Switching to process 7123] Running… 2010-01-03 12:39:47.790 Formatter[7123:a0f] NSCFString Cell Title 2010-01-03 12:39:47.810 Formatter[7123:a0f] Foo Foo: 0x1139291d0 2010-01-03 12:39:47.811 Formatter[7123:a0f] Foo Foo: 0x1151000a0 2010-01-03 12:39:47.811 Formatter[7123:a0f] Foo Foo: 0x1151000b0 Therefore you have too prepare to receive at least one object, which is not Foo. Interestingly, I could not find that little detail in the documentation. If you want to return an instance Foo from your datasource, it is much more convenient to write your own NSCell subclass, because you can control editing and formatting much easier. You can even use an attached formatter that you setup in IB, passing it a property of Foo. All the best, Patrick On Jan 3, 2010, at 1:47 , Henri Häkkinen wrote: Hello. I have an array of custom Foo objects which I would need to display in an NSTableView object. I implement the data source delegate like this: - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return [arrayOfFoos count]; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger) row { return [arrayOfFoos objectAtIndex:row]; } Then I have NSFormatter subclass FooFormatter which takes in a Foo object and converts it to a string. This formatter object is attached to the formatter property of the TextFieldCell class in the NSTableView's table column. The FooFormatter is like this: @implementation FooFormatter - (NSString *)stringForObjectValue:(id)anObject { if ([anObject isKindOfClass:[Foo class]] == NO) { [NSException raise:NSInvalidArgumentException format:@Wrong object]; } Foo *foo = (Foo *)anObject; NSString *string; // ... convert foo into string ... return string; } @end I am assuming here that the object returned by the data source objectValueForTableColumn: is passed to the formatter's stringForObjectValue: before it is displayed in the text field cell -- this seems not to be the case. I would like to keep formatting of Foo objects separate from the data source (if possible) since I intend to implement multiple different FooFormatter derived classes suited for different situations. The Cocoa docs seem to be a little low on details on how these NSFormatter objects are supposed to work. Can anybody give me any insight? Would be appreciated. Thanks. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/pmau%40me.com This email sent to p...@me.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not
Re: Custom NSFormatter classes
Hallo Henri I have updated the Formatter to include a context menu for the TableView. http://public.me.com/pmau Since you don't know the target, you could wire them up to the FirstResponder object in IB. Look at the inspector panel for FirstResponder, you can add actions there. Since the TableView is not subclassed, the first responder in this case is the Application Delegate. This is where I implemented the actions. This is not how I would recommend implementing, but it should give you an idea. Please read http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/MenuList/Articles/EnablingMenuItems.html It explains how the responder chain is searched and how enabling items works. In my example: * NSTableView does not implent it, * The NSWinow does not implement it * The widow delegate does not * The Application delegate does (Bingo!) You could look at the [window firstResponder] in the action method, this would yield the TableView. You could then mis-use the Datasource and forward the action there. (You can get the selected rows there, too.) You could subclass the NSTableView, implementing your actions there. You could embed the TableView in a custom view subclass to handle actions and so on. You could use a custom Controller as your FilesOwner and bind actions there in IB. I hope you get the idea. Patrick PS: I don't mind answering, but my quick hacks will not necessarily improve your coding ;) Please read a lot of documents about FirstResponder, FilesOwner and see what fits your needs. On Jan 4, 2010, at 19:14 , Henri Häkkinen wrote: Hello again Patric and others. I have another question related to the previous one. I now have the following things: * Foo model class * FooFormatter class which converts Foo objects into string representations * User interface with NSTableView which uses the FooFormatter in a text field cell What I would like to do next (yet not sure how to do it) is to have a context menu attached to the table view with menu items calling actions on a Foo object underneath the mouse cursor. Lets consider that the Foo class has something like the following: - (IBAction)setOneDot:(id)sender; - (IBAction)setTwoDots:(id)sender; - (IBAction)setThreeDots:(id)sender; And the context menu would have items like One dot, Two dots and Three dots which would call those actions. The problem here is that target-action relationships can't be bound in the Interface Builder, since target is not known until the user presses right mouse on the table view. I am guessing that the best solution would be to subclass NSCell or NSTextFieldCell and then override some method to handle the mouse event? Or maybe this could be done with some sort of Cocoa Bindings trickery to have those menu items call directly on the setDots: method of the Foo class, without having to implement a separate action for each setXXXDot(s) ? How about displaying a checkmark on the menu item for the current state? On Jan 3, 2010, at 1:58 PM, Patrick Mau wrote: Hallo Henri Your assumption about how formatters should work are correct. To provide a useful answer I have setup a mini project here, because I have stumbled over a detail I did not now: http://public.me.com/pmau I took your approach and implemted a minimal datasource and a Foo object. This is not a great example, but here's what II did not know: When you wire up the formatter to the text field cell in IB, setFormatter is called on the TextFieldCell, which in turn will call your formatting code withe the cell's title: run [Switching to process 7123] Running… 2010-01-03 12:39:47.790 Formatter[7123:a0f] NSCFString Cell Title 2010-01-03 12:39:47.810 Formatter[7123:a0f] Foo Foo: 0x1139291d0 2010-01-03 12:39:47.811 Formatter[7123:a0f] Foo Foo: 0x1151000a0 2010-01-03 12:39:47.811 Formatter[7123:a0f] Foo Foo: 0x1151000b0 Therefore you have too prepare to receive at least one object, which is not Foo. Interestingly, I could not find that little detail in the documentation. If you want to return an instance Foo from your datasource, it is much more convenient to write your own NSCell subclass, because you can control editing and formatting much easier. You can even use an attached formatter that you setup in IB, passing it a property of Foo. All the best, Patrick On Jan 3, 2010, at 1:47 , Henri Häkkinen wrote: Hello. I have an array of custom Foo objects which I would need to display in an NSTableView object. I implement the data source delegate like this: - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return [arrayOfFoos count]; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger) row { return [arrayOfFoos objectAtIndex:row]; } Then I have NSFormatter subclass FooFormatter which takes in a Foo object and converts it to a string.
Re: Custom NSFormatter classes
Thanks for your answer again, Patrick. By the way, what is the general opinion about the Cocoa Bindings technology among Mac developers? I have been looking into it lately and while it looks very neat I have found it troublesome to actually put it into practical use. I am contemplating whether or not to adopt it into my projects, or to just use target-action mechanism which seems to be easier to use even though it requires a bit more glue coding. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Custom NSFormatter classes
On Tuesday, January 5, 2010, Henri Häkkinen wrote: Thanks for your answer again, Patrick. By the way, what is the general opinion about the Cocoa Bindings technology among Mac developers? Don't confuse my uninformed opinion with the general opinion but it appears to be an 80% technology... 80% of the time (particularly for simple cases) it works well saves a bit of effort. For the remaining 20% it varies significantly; sometimes you can bend it, prod it and squish it to mostly fit... Sometimes you waste several hours bending, prodding squishing only to realise those several hours of effort (assuming you were successful) saved you five or ten minutes of glue coding. My difficulty is knowing which situation is which. Plus often you will get both situations in the one project... Regards, Matt ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Custom NSFormatter classes
Hallo Henri Your assumption about how formatters should work are correct. To provide a useful answer I have setup a mini project here, because I have stumbled over a detail I did not now: http://public.me.com/pmau I took your approach and implemted a minimal datasource and a Foo object. This is not a great example, but here's what II did not know: When you wire up the formatter to the text field cell in IB, setFormatter is called on the TextFieldCell, which in turn will call your formatting code withe the cell's title: run [Switching to process 7123] Running… 2010-01-03 12:39:47.790 Formatter[7123:a0f] NSCFString Cell Title 2010-01-03 12:39:47.810 Formatter[7123:a0f] Foo Foo: 0x1139291d0 2010-01-03 12:39:47.811 Formatter[7123:a0f] Foo Foo: 0x1151000a0 2010-01-03 12:39:47.811 Formatter[7123:a0f] Foo Foo: 0x1151000b0 Therefore you have too prepare to receive at least one object, which is not Foo. Interestingly, I could not find that little detail in the documentation. If you want to return an instance Foo from your datasource, it is much more convenient to write your own NSCell subclass, because you can control editing and formatting much easier. You can even use an attached formatter that you setup in IB, passing it a property of Foo. All the best, Patrick On Jan 3, 2010, at 1:47 , Henri Häkkinen wrote: Hello. I have an array of custom Foo objects which I would need to display in an NSTableView object. I implement the data source delegate like this: - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return [arrayOfFoos count]; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger) row { return [arrayOfFoos objectAtIndex:row]; } Then I have NSFormatter subclass FooFormatter which takes in a Foo object and converts it to a string. This formatter object is attached to the formatter property of the TextFieldCell class in the NSTableView's table column. The FooFormatter is like this: @implementation FooFormatter - (NSString *)stringForObjectValue:(id)anObject { if ([anObject isKindOfClass:[Foo class]] == NO) { [NSException raise:NSInvalidArgumentException format:@Wrong object]; } Foo *foo = (Foo *)anObject; NSString *string; // ... convert foo into string ... return string; } @end I am assuming here that the object returned by the data source objectValueForTableColumn: is passed to the formatter's stringForObjectValue: before it is displayed in the text field cell -- this seems not to be the case. I would like to keep formatting of Foo objects separate from the data source (if possible) since I intend to implement multiple different FooFormatter derived classes suited for different situations. The Cocoa docs seem to be a little low on details on how these NSFormatter objects are supposed to work. Can anybody give me any insight? Would be appreciated. Thanks. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/pmau%40me.com This email sent to p...@me.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Custom NSFormatter classes
Hello Patric. I was able to get the NSFormatter subclass to work properly by ignoring all non-Foo objects sent to it. The Cocoa docs are indeed lacking in this respect as there is no mentioning that the cell's title will first be sent. To me this feels a bit odd anyway since I can think of no reason why should the NSFormatter be concerned about it. Subclassing an NSCell class seemed to me a bit overcomplicated for this task so I am going with the NSFormatter. Thanks for the suggestion though. On Jan 3, 2010, at 1:58 PM, Patrick Mau wrote: Hallo Henri Your assumption about how formatters should work are correct. To provide a useful answer I have setup a mini project here, because I have stumbled over a detail I did not now: http://public.me.com/pmau I took your approach and implemted a minimal datasource and a Foo object. This is not a great example, but here's what II did not know: When you wire up the formatter to the text field cell in IB, setFormatter is called on the TextFieldCell, which in turn will call your formatting code withe the cell's title: run [Switching to process 7123] Running… 2010-01-03 12:39:47.790 Formatter[7123:a0f] NSCFString Cell Title 2010-01-03 12:39:47.810 Formatter[7123:a0f] Foo Foo: 0x1139291d0 2010-01-03 12:39:47.811 Formatter[7123:a0f] Foo Foo: 0x1151000a0 2010-01-03 12:39:47.811 Formatter[7123:a0f] Foo Foo: 0x1151000b0 Therefore you have too prepare to receive at least one object, which is not Foo. Interestingly, I could not find that little detail in the documentation. If you want to return an instance Foo from your datasource, it is much more convenient to write your own NSCell subclass, because you can control editing and formatting much easier. You can even use an attached formatter that you setup in IB, passing it a property of Foo. All the best, Patrick ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Custom NSFormatter classes
Hello. I have an array of custom Foo objects which I would need to display in an NSTableView object. I implement the data source delegate like this: - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return [arrayOfFoos count]; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger) row { return [arrayOfFoos objectAtIndex:row]; } Then I have NSFormatter subclass FooFormatter which takes in a Foo object and converts it to a string. This formatter object is attached to the formatter property of the TextFieldCell class in the NSTableView's table column. The FooFormatter is like this: @implementation FooFormatter - (NSString *)stringForObjectValue:(id)anObject { if ([anObject isKindOfClass:[Foo class]] == NO) { [NSException raise:NSInvalidArgumentException format:@Wrong object]; } Foo *foo = (Foo *)anObject; NSString *string; // ... convert foo into string ... return string; } @end I am assuming here that the object returned by the data source objectValueForTableColumn: is passed to the formatter's stringForObjectValue: before it is displayed in the text field cell -- this seems not to be the case. I would like to keep formatting of Foo objects separate from the data source (if possible) since I intend to implement multiple different FooFormatter derived classes suited for different situations. The Cocoa docs seem to be a little low on details on how these NSFormatter objects are supposed to work. Can anybody give me any insight? Would be appreciated. Thanks. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com