NSButton
サブクラスを として機能させるためのいくつかの例に従いましたNSColorWell
(NSButton
サブクラスは既に必要な外観動作を提供しているため)、しかし、ボタンを使用してパネルを呼び出して色を変更した後、の色も変更されていることに気付きましたドキュメントで選択したテキスト。代わりに、外観のカスタマイズでサブクラス化した場合NSColorWell
、この問題は発生しませんか?
ただし、それを回避し、ボタンのサブクラスを引き続き使用できる回避策を期待しています。ボタン自体をファーストレスポンダーにすることを提案するディスカッションスレッドを見たことがありますが、ボタンが別のパレットにあるため、これを機能させるのに問題があります。また、レスポンダー チェーンを変更したり、パレットをキー ウィンドウにしたりしたくありません。NSColorPanel
setColor: をオーバーライドして、予想される通知を投稿するが、最初のレスポンダーに触れないようにするカテゴリは、どれほど悪でしょうか?
(注:カラーパネルを開くだけでなく、現在BFColorPickerPopover
DrummerB https://github.com/DrummerB/BFColorPickerPopoverを利用しています。しかし、それはそれほど複雑ではないと思います。私は同じNSColorPanel
/最初に持っていました統合する前のレスポンダーの問題)。
NSColorPanel
ソースコードを投稿するように求められたので、ここに私の NSButton サブクラスからの関連ビットを示します (直接ではなく、上記のピッカー ポップオーバーを使用することに注意してください)。
.h:
@interface ...
@property (nonatomic, strong) NSColor *color;
@property (nonatomic, assign) BOOL active;
@property (nonatomic, strong) NSColor *buttonColor;
@property (nonatomic, weak) BFColorPickerPopover *popover;
- (void)activate:(BOOL)exclusive; // param ignored, always exclusive
- (void)activate;
- (void)deactivate;
- (void)takeColorFrom:(id)sender;
@end
.m:
@implementation ...
@dynamic color;
- (NSColor *)color
{
return self.buttonColor;
}
- (void)setColor:(NSColor *)newColor
{
self.buttonColor = newColor;
[self generateSwatch];
self.needsDisplay = YES;
self.popover.color = newColor;
}
- (void)activate:(BOOL)exclusive
{
[self activate]; // always exclusive
}
- (void)activate
{
self.popover = [BFColorPickerPopover sharedPopover];
self.popover.color = self.buttonColor;
[self.popover showRelativeToRect:self.frame ofView:self.superview
preferredEdge:self.preferredEdgeForPopover];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(popoverDidClose:)
name:NSPopoverDidCloseNotification
object:self.popover];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(colorDidChange:)
name:NSColorPanelColorDidChangeNotification
object:self.popover.colorPanel];
activeButton = self;
self.active = YES;
}
- (void)deactivate
{
if (self.popover)
{
[self.popover close];
self.popover = nil;
}
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSPopoverDidCloseNotification object:self.popover];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSColorPanelColorDidChangeNotification
object:self.popover.colorPanel];
if (activeButton == self) activeButton = nil;
self.active = NO;
}
- (void)popoverDidClose:(NSNotification *)notification
{
self.popover = nil; // don't let deactivate ask it to close again
[self deactivate];
}
- (void)colorDidChange:(NSNotification *)notification
{
self.buttonColor = self.popover.colorPanel.color;
[self generateSwatch];
self.needsDisplay = YES;
[self sendAction:self.action to:self.target];
}
- (void)mouseDown:(NSEvent *)theEvent
{
if (self.isEnabled && !self.active)
[self activate];
else if (self.active)
[self deactivate];
}
- (void)takeColorFrom:(id)sender
{
if ([sender respondsToSelector:@selector(color)])
self.color = [sender color];
}
@end
補遺:
NSColorWell
NSButton サブクラスの代わりに法線を使用してみましたが、同じ問題が発生しました。changeColor:
パネルで選択された色は、アクション メソッドの呼び出しに加えて、ファーストレスポンダを呼び出します。私の質問のすべてを忘れてNSButton
、一般的に、どのようにNSColorWell
色をファーストレスポンダにも押し付けてはいけませんか? 予想されるファーストレスポンダーをカスタマイズして選択的に無視するchangeColor:
必要がありNSColorWell
ますか、それともファーストレスポンダーを本当にやるべきこと、または何か他のものにしていますか?