source: trunk/Cocoa/Pester/Source/NJRHotKeyField.m@ 580

Last change on this file since 580 was 572, checked in by Nicholas Riley, 15 years ago

Support tabbing in preferences panel.

File size: 6.1 KB
RevLine 
[129]1//
2// NJRHotKeyField.m
3// Pester
4//
5// Created by Nicholas Riley on Sat Mar 29 2003.
6// Copyright (c) 2003 Nicholas Riley. All rights reserved.
7//
8
9#import "NJRHotKeyField.h"
10#import "NJRHotKeyFieldCell.h"
[131]11#import "NJRHotKey.h"
[129]12#import "NSString-NJRExtensions.h"
13
[130]14static const NSRange zeroRange = {0, 0};
15static const unsigned int capturedModifierMask = (NSShiftKeyMask |
16 NSControlKeyMask |
17 NSAlternateKeyMask |
18 NSCommandKeyMask);
19
[129]20static NSParagraphStyle *leftAlignStyle = nil, *centerAlignStyle = nil;
21static NSDictionary *statusAttributes = nil;
22
[130]23@implementation NJRHotKeyField
24
[129]25+ (void)initialize;
26{
27 NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
28 [paraStyle setAlignment: NSLeftTextAlignment];
29 leftAlignStyle = [paraStyle copy];
30 [paraStyle setAlignment: NSCenterTextAlignment];
31 centerAlignStyle = [paraStyle copy];
32 [paraStyle release];
33
34 statusAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
35 [NSFont systemFontOfSize: [NSFont labelFontSize]], NSFontAttributeName,
36 centerAlignStyle, NSParagraphStyleAttributeName, nil];
37}
38
39- (void)_setUp;
40{
41 [self setAllowsEditingTextAttributes: YES];
42 [self setImportsGraphics: NO];
43 [self cell]->isa = [NJRHotKeyFieldCell class];
44}
45
[131]46#pragma mark initialize-release
47
[129]48- (id)initWithCoder:(NSCoder *)coder;
49{
50 if ( (self = [super initWithCoder: coder]) != nil) {
51 [self _setUp];
52 }
53 return self;
54}
55
56- (id)initWithFrame:(NSRect)frameRect;
57{
58 if ( (self = [super initWithFrame: frameRect]) != nil) {
59 [self _setUp];
60 }
61 return self;
62}
63
[131]64- (void)dealloc;
65{
66 [hotKey release];
[355]67 [super dealloc];
[131]68}
69
70#pragma mark interface updating
71
[132]72- (void)showStatus:(NSString *)error;
73{
74 [self setAttributedStringValue:
75 [[NSAttributedString alloc] initWithString: [NSString stringWithFormat: @"(%@)", error]
76 attributes: statusAttributes]];
77 [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(clearStatus) object: nil];
78 [self performSelector: @selector(clearStatus) withObject: nil afterDelay: 0.5];
79 [[self currentEditor] setSelectedRange: zeroRange];
80}
[129]81
82- (void)previewKeyEquivalentAttributedString:(NSAttributedString *)equivString;
83{
84 NSMutableAttributedString *previewString = [equivString mutableCopy];
85 [previewString addAttribute: NSParagraphStyleAttributeName value: leftAlignStyle range: NSMakeRange(0, [previewString length])];
86 [self setAttributedStringValue: previewString];
87 [[self currentEditor] setSelectedRange: zeroRange];
88 [previewString release];
89}
90
91- (void)showKeyEquivalentAttributedStringFinalized:(BOOL)finalized;
92{
[131]93 if ([hotKey characters] == nil) {
[129]94 [self showStatus: @"none assigned"];
95 return;
96 }
[131]97 NSMutableAttributedString *equivString = [[[hotKey characters] keyEquivalentAttributedStringWithModifierFlags: [hotKey modifierFlags]] mutableCopy];
[129]98 [equivString addAttribute: NSParagraphStyleAttributeName
99 value: (finalized ? centerAlignStyle : leftAlignStyle)
100 range: NSMakeRange(0, [equivString length])];
101 [self setAttributedStringValue: equivString];
102 [[self currentEditor] setSelectedRange: zeroRange];
103 [equivString release];
104}
105
[132]106- (void)clearStatus;
107{
108 if ([[[self attributedStringValue] attributesAtIndex: 0 effectiveRange: NULL] isEqualToDictionary: statusAttributes]) {
109 [self showKeyEquivalentAttributedStringFinalized: ([[NSApp currentEvent] modifierFlags] & capturedModifierMask) == 0];
110 }
111}
112
[572]113- (void)textDidEndEditing:(NSNotification *)notification;
114{
115 [self showKeyEquivalentAttributedStringFinalized: YES];
116 [super textDidEndEditing: notification];
117}
118
[131]119#pragma mark event handling
[129]120
121- (void)keyUp:(NSEvent *)theEvent;
122{
123 NSString *characters = [theEvent charactersIgnoringModifiers];
[130]124 int length = [characters length];
125 if (length > 1) {
[129]126 [self showStatus: @"please press only one non-modifier key"];
127 return;
128 }
[130]129 if (length == 1) {
130 unsigned modifierFlags = ([theEvent modifierFlags] & capturedModifierMask);
131 id delegate = [self delegate];
132 NSString *message = nil;
[572]133 unichar character = [characters characterAtIndex: 0];
134 if (character == NSTabCharacter || character == NSBackTabCharacter)
135 return;
136 if (delegate != nil && ![delegate hotKeyField: self shouldAcceptCharacter: character modifierFlags: modifierFlags rejectionMessage: &message]) {
[130]137 [self showStatus: message != nil ? message : @"key is unavailable for use"];
138 } else {
[131]139 [self setHotKey: [NJRHotKey hotKeyWithCharacters: characters modifierFlags: modifierFlags keyCode: [theEvent keyCode]]];
[130]140 [NSApp sendAction: [self action] to: [self target] from: self];
141 [self showKeyEquivalentAttributedStringFinalized: ([theEvent modifierFlags] & capturedModifierMask) == 0];
142 }
143 }
[129]144}
145
146- (BOOL)performKeyEquivalent:(NSEvent *)theEvent;
147{
[572]148 if ([[self window] firstResponder] == self)
149 [self keyUp: theEvent];
[129]150 return [super performKeyEquivalent: theEvent];
151}
152
153- (void)flagsChanged:(NSEvent *)theEvent;
154{
155 unsigned modifierFlags = [theEvent modifierFlags];
156
[130]157 if ((modifierFlags & capturedModifierMask) == 0) {
[129]158 [self showKeyEquivalentAttributedStringFinalized: YES];
159 } else {
160 [self previewKeyEquivalentAttributedString:
[130]161 [@"" keyEquivalentAttributedStringWithModifierFlags: modifierFlags]];
[129]162 }
163}
164
[131]165#pragma mark acccessing
166
167- (NJRHotKey *)hotKey;
[129]168{
[131]169 return hotKey;
[129]170}
171
[131]172- (void)setHotKey:(NJRHotKey *)aKey;
[130]173{
[131]174 if (aKey != hotKey) {
175 [hotKey release];
176 hotKey = [aKey retain];
177 [self showKeyEquivalentAttributedStringFinalized: ([[NSApp currentEvent] modifierFlags] & capturedModifierMask) == 0];
178 }
[130]179}
180
[131]181#pragma mark actions
182
183- (IBAction)clear:(id)sender;
[130]184{
[131]185 [self setHotKey: nil];
186 [NSApp sendAction: [self action] to: [self target] from: self];
187 [self showKeyEquivalentAttributedStringFinalized: YES];
[130]188}
189
[129]190@end
Note: See TracBrowser for help on using the repository browser.