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

Last change on this file since 309 was 132, checked in by Nicholas Riley, 22 years ago

NJRHotKeyField.m: Fixed status-available-forever problem. Rearranged
some stuff.

File size: 5.7 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 "NJRHotKey.h"
12#import "NSString-NJRExtensions.h"
13
14static const NSRange zeroRange = {0, 0};
15static const unsigned int capturedModifierMask = (NSShiftKeyMask |
16 NSControlKeyMask |
17 NSAlternateKeyMask |
18 NSCommandKeyMask);
19
20static NSParagraphStyle *leftAlignStyle = nil, *centerAlignStyle = nil;
21static NSDictionary *statusAttributes = nil;
22
23@implementation NJRHotKeyField
24
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
46#pragma mark initialize-release
47
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
64- (void)dealloc;
65{
66 [hotKey release];
67}
68
69#pragma mark interface updating
70
71- (void)showStatus:(NSString *)error;
72{
73 [self setAttributedStringValue:
74 [[NSAttributedString alloc] initWithString: [NSString stringWithFormat: @"(%@)", error]
75 attributes: statusAttributes]];
76 [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(clearStatus) object: nil];
77 [self performSelector: @selector(clearStatus) withObject: nil afterDelay: 0.5];
78 [[self currentEditor] setSelectedRange: zeroRange];
79}
80
81- (void)previewKeyEquivalentAttributedString:(NSAttributedString *)equivString;
82{
83 NSMutableAttributedString *previewString = [equivString mutableCopy];
84 [previewString addAttribute: NSParagraphStyleAttributeName value: leftAlignStyle range: NSMakeRange(0, [previewString length])];
85 [self setAttributedStringValue: previewString];
86 [[self currentEditor] setSelectedRange: zeroRange];
87 [previewString release];
88}
89
90- (void)showKeyEquivalentAttributedStringFinalized:(BOOL)finalized;
91{
92 if ([hotKey characters] == nil) {
93 [self showStatus: @"none assigned"];
94 return;
95 }
96 NSMutableAttributedString *equivString = [[[hotKey characters] keyEquivalentAttributedStringWithModifierFlags: [hotKey modifierFlags]] mutableCopy];
97 [equivString addAttribute: NSParagraphStyleAttributeName
98 value: (finalized ? centerAlignStyle : leftAlignStyle)
99 range: NSMakeRange(0, [equivString length])];
100 [self setAttributedStringValue: equivString];
101 [[self currentEditor] setSelectedRange: zeroRange];
102 [equivString release];
103}
104
105- (void)clearStatus;
106{
107 if ([[[self attributedStringValue] attributesAtIndex: 0 effectiveRange: NULL] isEqualToDictionary: statusAttributes]) {
108 [self showKeyEquivalentAttributedStringFinalized: ([[NSApp currentEvent] modifierFlags] & capturedModifierMask) == 0];
109 }
110}
111
112#pragma mark event handling
113
114- (void)keyUp:(NSEvent *)theEvent;
115{
116 NSString *characters = [theEvent charactersIgnoringModifiers];
117 int length = [characters length];
118 if (length > 1) {
119 [self showStatus: @"please press only one non-modifier key"];
120 return;
121 }
122 if (length == 1) {
123 unsigned modifierFlags = ([theEvent modifierFlags] & capturedModifierMask);
124 id delegate = [self delegate];
125 NSString *message = nil;
126 if (delegate != nil && ![delegate hotKeyField: self shouldAcceptCharacter: [characters characterAtIndex: 0] modifierFlags: modifierFlags rejectionMessage: &message]) {
127 [self showStatus: message != nil ? message : @"key is unavailable for use"];
128 } else {
129 [self setHotKey: [NJRHotKey hotKeyWithCharacters: characters modifierFlags: modifierFlags keyCode: [theEvent keyCode]]];
130 [NSApp sendAction: [self action] to: [self target] from: self];
131 [self showKeyEquivalentAttributedStringFinalized: ([theEvent modifierFlags] & capturedModifierMask) == 0];
132 }
133 }
134}
135
136- (BOOL)performKeyEquivalent:(NSEvent *)theEvent;
137{
138 [self keyUp: theEvent];
139 return [super performKeyEquivalent: theEvent];
140}
141
142- (void)flagsChanged:(NSEvent *)theEvent;
143{
144 unsigned modifierFlags = [theEvent modifierFlags];
145
146 if ((modifierFlags & capturedModifierMask) == 0) {
147 [self showKeyEquivalentAttributedStringFinalized: YES];
148 } else {
149 [self previewKeyEquivalentAttributedString:
150 [@"" keyEquivalentAttributedStringWithModifierFlags: modifierFlags]];
151 }
152}
153
154#pragma mark acccessing
155
156- (NJRHotKey *)hotKey;
157{
158 return hotKey;
159}
160
161- (void)setHotKey:(NJRHotKey *)aKey;
162{
163 if (aKey != hotKey) {
164 [hotKey release];
165 hotKey = [aKey retain];
166 [self showKeyEquivalentAttributedStringFinalized: ([[NSApp currentEvent] modifierFlags] & capturedModifierMask) == 0];
167 }
168}
169
170#pragma mark actions
171
172- (IBAction)clear:(id)sender;
173{
174 [self setHotKey: nil];
175 [NSApp sendAction: [self action] to: [self target] from: self];
176 [self showKeyEquivalentAttributedStringFinalized: YES];
177}
178
179@end
Note: See TracBrowser for help on using the repository browser.