Re: Add bindings for custom menu items' isHidden to (an attribute of) a custom object?
Re: Add bindings for custom menu items' isHidden to (an attribute of) a custom object?
- Subject: Re: Add bindings for custom menu items' isHidden to (an attribute of) a custom object?
- From: Daryle Walker <email@hidden>
- Date: Mon, 08 Sep 2014 17:10:12 -0400
On Sep 8, 2014, at 4:21 AM, Daryle Walker <email@hidden> wrote:
> The test value and the target menu were always the same. Four runs of double NULL then four more with Today’s sub-menu (Sep. 8). So the transformer always returns YES and every per-day history menu item (and sub-menu) is hidden. How do I get “dayItem.submenu” to be the operand for the transformer? Did I mess up the binding? Or the transformer’s very design? Where did those 4 NULL runs come from?
>
> …
>
> Oh, for that last question, it’s because the “sourceMenu” property starts as NIL and I don’t change it until I create the per-day menus. It would have to be that way since I set the property to the sub-menu of the newest day (unless it’s before Today).
I can’t change the operand, so I had to change the operation:
> @interface MyObjectIdentityTransformer : NSValueTransformer
>
> //! Starts as nil; the instance to be compared.
> @property (nonatomic) id compared;
>
> @end
>
> @implementation MyObjectIdentityTransformer
>
> + (Class)transformedValueClass {
> return [NSNumber class];
> }
>
> + (BOOL)allowsReverseTransformation {
> return NO;
> }
>
> - (id)transformedValue:(id)value {
> return [NSNumber numberWithBool:(self.compared == value)];
> }
>
> @end
>
> static inline
> NSMenuItem * CreateMenuItemForDay(NSCalendarDate *day, NSDateFormatter *format) {
> NSString * const dayTitle = [format stringFromDate:day];
> NSMenu * const daySubmenu = [[NSMenu alloc] initWithTitle:dayTitle];
> NSMenuItem * const dayItem = [[NSMenuItem alloc] initWithTitle:dayTitle action:NULL keyEquivalent:@""];
>
> dayItem.representedObject = day;
> dayItem.submenu = daySubmenu;
>
> // Attach a binding to let the menu item auto-hide when used as the Today menu item.
> MyAppDelegate * const appDelegate = [NSApp delegate];
> MyObjectIdentityTransformer * const transformer = [[MyObjectIdentityTransformer alloc] init];
>
> transformer.compared = dayItem.submenu;
> [dayItem bind:NSHiddenBinding toObject:appDelegate.myOverflowMenuController withKeyPath:MyKeyPathSourceMenu options:@{NSValueTransformerBindingOption: transformer}];
> return dayItem;
> }
Each point of a binding is described by two aspects: an object and a (not necessarily direct) attribute of the object. In the -bind:toObject:withKeyPath:options: method, the bound point is the receiver and first argument and the source point is the second and third arguments. When using a value transformer in forward mode, the operand is always the source point. So when I had the transformer as an attribute of the source point, both the operand and the stored menu were always the same: the current Today menu. Now I have the transformer associated with the per-day menu item (i.e. the bound point), so I compare its sub-menu with the current Today menu (the operand).
I was going to change the menu item’s representedObject to store the transformer, but then I realized that since the value transformer is part of a NSDictionary, the dictionary will do a retain and so I can make the transformer a loosely-associated object.
—
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden