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

Last change on this file since 130 was 130, checked in by Nicholas Riley, 21 years ago

PSPreferencesController.[hm]: Filter hot keys. Read and write to
preferences.

NJRHotKeyField.[hm]: Added property list serialization of hot key data
(not quite like PSAlarm/Alert because we're a GUI element). Added
delegate method for hot key filtering and action triggering when hot
key set or cleared. Only use filtered modifiers to avoid bizarre
behavior. More bug fixes.

English.lproj/Preferences.nib: Connected Clear button. Connected
NJRHotKeyField delegate and target to PSPreferencesController.

NSString-NJRExtensions.[hm]: Replaced "...modifierMask" with
"...modifierFlags" because it's more appropriate.

File size: 6.0 KB
Line 
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"
11#import "NSString-NJRExtensions.h"
12
13// property list keys
14static NSString * const PLCharacters = @"characters"; // NSString
15static NSString * const PLModifierFlags = @"modifierFlags"; // NSNumber
16static NSString * const PLKeyCode = @"keyCode"; // NSNumber
17
18static const NSRange zeroRange = {0, 0};
19static const unsigned int capturedModifierMask = (NSShiftKeyMask |
20 NSControlKeyMask |
21 NSAlternateKeyMask |
22 NSCommandKeyMask);
23
24static NSParagraphStyle *leftAlignStyle = nil, *centerAlignStyle = nil;
25static NSDictionary *statusAttributes = nil;
26
27@implementation NJRHotKeyField
28
29+ (void)initialize;
30{
31 NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
32 [paraStyle setAlignment: NSLeftTextAlignment];
33 leftAlignStyle = [paraStyle copy];
34 [paraStyle setAlignment: NSCenterTextAlignment];
35 centerAlignStyle = [paraStyle copy];
36 [paraStyle release];
37
38 statusAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
39 [NSFont systemFontOfSize: [NSFont labelFontSize]], NSFontAttributeName,
40 centerAlignStyle, NSParagraphStyleAttributeName, nil];
41}
42
43- (void)_setUp;
44{
45 [self setAllowsEditingTextAttributes: YES];
46 [self setImportsGraphics: NO];
47 [self cell]->isa = [NJRHotKeyFieldCell class];
48}
49
50- (id)initWithCoder:(NSCoder *)coder;
51{
52 if ( (self = [super initWithCoder: coder]) != nil) {
53 [self _setUp];
54 }
55 return self;
56}
57
58- (id)initWithFrame:(NSRect)frameRect;
59{
60 if ( (self = [super initWithFrame: frameRect]) != nil) {
61 [self _setUp];
62 }
63 return self;
64}
65
66// XXX still problems with command-A the first time
67
68- (void)previewKeyEquivalentAttributedString:(NSAttributedString *)equivString;
69{
70 NSMutableAttributedString *previewString = [equivString mutableCopy];
71 [previewString addAttribute: NSParagraphStyleAttributeName value: leftAlignStyle range: NSMakeRange(0, [previewString length])];
72 [self setAttributedStringValue: previewString];
73 [[self currentEditor] setSelectedRange: zeroRange];
74 [previewString release];
75}
76
77- (void)showStatus:(NSString *)error;
78{
79 [self setAttributedStringValue:
80 [[NSAttributedString alloc] initWithString: [NSString stringWithFormat: @"(%@)", error]
81 attributes: statusAttributes]];
82 [[self currentEditor] setSelectedRange: zeroRange];
83}
84
85- (void)showKeyEquivalentAttributedStringFinalized:(BOOL)finalized;
86{
87 if (hotKeyCharacters == nil) {
88 [self showStatus: @"none assigned"];
89 return;
90 }
91 NSMutableAttributedString *equivString = [[hotKeyCharacters keyEquivalentAttributedStringWithModifierFlags: hotKeyModifierFlags] mutableCopy];
92 [equivString addAttribute: NSParagraphStyleAttributeName
93 value: (finalized ? centerAlignStyle : leftAlignStyle)
94 range: NSMakeRange(0, [equivString length])];
95 [self setAttributedStringValue: equivString];
96 [[self currentEditor] setSelectedRange: zeroRange];
97 [equivString release];
98}
99
100- (void)clearHotKey;
101{
102 [hotKeyCharacters release];
103 hotKeyCharacters = nil;
104 hotKeyModifierFlags = 0;
105 hotKeyCode = 0;
106 [NSApp sendAction: [self action] to: [self target] from: self];
107}
108
109- (void)keyUp:(NSEvent *)theEvent;
110{
111 NSString *characters = [theEvent charactersIgnoringModifiers];
112 int length = [characters length];
113 if (length > 1) {
114 [self showStatus: @"please press only one non-modifier key"];
115 return;
116 }
117 if (length == 1) {
118 unsigned modifierFlags = ([theEvent modifierFlags] & capturedModifierMask);
119 id delegate = [self delegate];
120 NSString *message = nil;
121 if (delegate != nil && ![delegate hotKeyField: self shouldAcceptCharacter: [characters characterAtIndex: 0] modifierFlags: modifierFlags rejectionMessage: &message]) {
122 [self showStatus: message != nil ? message : @"key is unavailable for use"];
123 } else {
124 [hotKeyCharacters release];
125 hotKeyCharacters = [characters retain];
126 hotKeyModifierFlags = modifierFlags;
127 hotKeyCode = [theEvent keyCode];
128 [NSApp sendAction: [self action] to: [self target] from: self];
129 [self showKeyEquivalentAttributedStringFinalized: ([theEvent modifierFlags] & capturedModifierMask) == 0];
130 }
131 }
132}
133
134- (BOOL)performKeyEquivalent:(NSEvent *)theEvent;
135{
136 [self keyUp: theEvent];
137 return [super performKeyEquivalent: theEvent];
138}
139
140- (void)flagsChanged:(NSEvent *)theEvent;
141{
142 unsigned modifierFlags = [theEvent modifierFlags];
143
144 if ((modifierFlags & capturedModifierMask) == 0) {
145 [self showKeyEquivalentAttributedStringFinalized: YES];
146 } else {
147 [self previewKeyEquivalentAttributedString:
148 [@"" keyEquivalentAttributedStringWithModifierFlags: modifierFlags]];
149 }
150}
151
152- (IBAction)clear:(id)sender;
153{
154 [self clearHotKey];
155 [self showKeyEquivalentAttributedStringFinalized: YES];
156}
157
158#pragma mark property list serialization (Pester 1.1)
159
160- (NSDictionary *)propertyListRepresentation;
161{
162 return [NSDictionary dictionaryWithObjectsAndKeys:
163 hotKeyCharacters, PLCharacters,
164 [NSNumber numberWithUnsignedInt: hotKeyModifierFlags], PLModifierFlags,
165 [NSNumber numberWithUnsignedShort: hotKeyCode], PLKeyCode,
166 nil];
167}
168
169- (void)setFromPropertyList:(NSDictionary *)dict;
170{
171 NS_DURING
172 hotKeyCharacters = [[dict objectForKey: PLCharacters] retain];
173 hotKeyModifierFlags = [[dict objectForKey: PLModifierFlags] unsignedIntValue];
174 hotKeyCode = [[dict objectForKey: PLKeyCode] unsignedShortValue];
175 [self showKeyEquivalentAttributedStringFinalized: ([[NSApp currentEvent] modifierFlags] & capturedModifierMask) == 0];
176 NS_HANDLER
177 [self clear: nil];
178 NS_ENDHANDLER
179}
180
181@end
Note: See TracBrowser for help on using the repository browser.