WizardKit  0.1
WKWizardPanel.m
1 /*
2  * WKWizardPanel.m
3  *
4  * Implementation of the WKWizardPanel class for the WizardKit framework
5  *
6  * Copyright (c) 2006, by Saso Kiselkov
7  *
8  * For license details please see the file COPYING included with this
9  * source distribution package.
10  */
11 
12 #import "WKWizardPanel.h"
13 
14 #import <Foundation/NSString.h>
15 #import <Foundation/NSBundle.h>
16 #import <Foundation/NSArray.h>
17 #import <Foundation/NSDictionary.h>
18 #import <Foundation/NSException.h>
19 #import <Foundation/NSNotification.h>
20 #import <Foundation/NSCoder.h>
21 
22 #import <AppKit/NSApplication.h>
23 
29 NSString * const WKWizardPanelDidChangeCurrentStageNotification
30  = @"WKWizardPanelDidChangeCurrentStageNotification";
31 
32 @interface WKWizardPanel (Private)
33 
34 - (void) setupForStage: (NSString *) aStage;
35 
36 @end
37 
63 @implementation WKWizardPanel
64 
65 - (void) dealloc
66 {
67  TEST_RELEASE(stages);
68  TEST_RELEASE(initialStage);
69 
70  [super dealloc];
71 }
72 
82 - (void) setStages: (NSArray *) someStages
83 {
84  if (isActive == YES)
85  {
86  [NSException raise: NSInternalInconsistencyException
87  format: _(@"-[WKWizardPanel setStages:]: panel already "
88  @"active - stages must be set before activating the panel.")];
89  }
90 
91  ASSIGNCOPY(stages, someStages);
92  DESTROY(initialStage);
93 }
94 
102 - (NSArray *) stages
103 {
104  return stages;
105 }
106 
115 - (void) setRunsInModalSession: (BOOL) flag
116 {
117  if (isActive == YES)
118  {
119  [NSException raise: NSInternalInconsistencyException
120  format: _(@"-[WKWizardPanel setRunsInModalSession:] "
121  @"panel already active - modality must be set before activating "
122  @"the panel.")];
123  }
124 
125  runsInModalSession = flag;
126 }
127 
135 - (BOOL) runsInModalSession
136 {
137  return runsInModalSession;
138 }
139 
146 - (void) setInitialStage: (NSString *) aStageName
147 {
148  if (aStageName != nil && [stages containsObject: aStageName] == NO)
149  {
150  [NSException raise: NSInvalidArgumentException
151  format: _(@"-[WKWizardPanel setInitialStage:]: "
152  @"invalid stage name passed. Stage \"%@\" not in stages list: %@."),
153  aStageName, stages];
154  }
155 
156  ASSIGN(initialStage, aStageName);
157 }
158 
166 - (NSString *) initialStage
167 {
168  return initialStage;
169 }
170 
177 - (void) setCentersBeforeActivating: (BOOL) flag
178 {
180 }
181 
190 {
192 }
193 
205 - (void) setCurrentStage: (NSString *) aStageName
206 {
207  currentStage = [stages indexOfObject: aStageName];
208  if (currentStage == NSNotFound)
209  {
210  [NSException raise: NSInvalidArgumentException
211  format: _(@"-[WKWizardPanel setCurrentStage:]: "
212  @"invalid stage name passed. Stage \"%@\" not in stages list: %@."),
213  aStageName, stages];
214  }
215 
216  [self setupForStage: aStageName];
217 
218  [[NSNotificationCenter defaultCenter]
219  postNotificationName: WKWizardPanelDidChangeCurrentStageNotification
220  object: self
221  userInfo: [NSDictionary dictionaryWithObject: aStageName
222  forKey: @"Stage"]];
223 }
224 
232 - (NSArray *) currentStage
233 {
234  return [stages objectAtIndex: currentStage];
235 }
236 
243 - (void) nextStage: (id) sender
244 {
245  if (currentStage + 1 < [stages count])
246  {
247  [self setCurrentStage: [stages objectAtIndex: currentStage + 1]];
248  }
249 }
250 
257 - (void) previousStage: (id) sender
258 {
259  if (currentStage > 0)
260  {
261  [self setCurrentStage: [stages objectAtIndex: currentStage - 1]];
262  }
263 }
264 
281 - (int) activate: (id) sender
282 {
283  if (isActive)
284  {
285  [NSException raise: NSInternalInconsistencyException
286  format: _(@"-[WKWizardPanel activate:]: panel "
287  @"already active.")];
288  }
289 
290  if ([stages count] == 0)
291  {
292  [NSException raise: NSInternalInconsistencyException
293  format: _(@"-[WKWizardPanel activate:]: no stages "
294  @"set. You must set the panel's stages before activating it.")];
295  }
296 
297  isActive = YES;
298 
299  if (initialStage != nil)
300  {
301  [self setCurrentStage: initialStage];
302  }
303  else
304  {
305  [self setCurrentStage: [stages objectAtIndex: 0]];
306  }
307 
309  {
310  [self center];
311  }
312 
313  if (runsInModalSession)
314  {
315  int code;
316 
317  code = [NSApp runModalForWindow: self];
318 
319  [self close];
320 
321  return code;
322  }
323  else
324  {
325  [self makeKeyAndOrderFront: nil];
326 
327  return NSRunStoppedResponse;
328  }
329 }
330 
342 - (void) deactivate: (id) sender
343 {
344  if (isActive == NO)
345  {
346  [NSException raise: NSInternalInconsistencyException
347  format: _(@"-[WKWizardPanel deactivate:]: panel "
348  @"not active.")];
349  }
350 
351  isActive = NO;
352 
353  if (runsInModalSession)
354  {
355  [NSApp stopModal];
356  }
357  else
358  {
359  [self close];
360  }
361 }
362 
372 - (void) deactivateWithCode: (int) code
373 {
374  if (isActive == NO)
375  {
376  [NSException raise: NSInternalInconsistencyException
377  format: _(@"-[WKWizardPanel deactivateWithCode:]: "
378  @"panel not active.")];
379  }
380 
381  if (runsInModalSession == NO)
382  {
383  [NSException raise: NSInternalInconsistencyException
384  format: _(@"-[WKWizardPanel deactivateWithCode]: "
385  @"panel was not run in modal session. Use \"-deactivate:\" to "
386  @"deactivate a non-modal panel instead.")];
387  }
388 
389  isActive = NO;
390 
391  [NSApp stopModalWithCode: code];
392 }
393 
399 - (BOOL) isActive
400 {
401  return isActive;
402 }
403 
404 // NSCoding protocol
405 
406 - (void) encodeWithCoder: (NSCoder*) aCoder
407 {
408  [super encodeWithCoder: aCoder];
409 
410  if ([aCoder allowsKeyedCoding])
411  {
412  [aCoder encodeBool: runsInModalSession
413  forKey: @"WKRunsInModalSessionFlag"];
414  [aCoder encodeBool: runsInModalSession
415  forKey: @"WKCentersBeforeActivatingFlag"];
416 
417  [aCoder encodeObject: stages forKey: @"WKStages"];
418  [aCoder encodeObject: initialStage forKey: @"WKInitialStage"];
419  }
420  else
421  {
422  [aCoder encodeValueOfObjCType: @encode(BOOL)
423  at: &runsInModalSession];
424  [aCoder encodeValueOfObjCType: @encode(BOOL)
425  at: &centersBeforeActivating];
426 
427  [aCoder encodeObject: stages];
428  [aCoder encodeObject: initialStage];
429  }
430 }
431 
432 - (id) initWithCoder: (NSCoder*) aDecoder
433 {
434  if ((self = [super initWithCoder: aDecoder]) != nil)
435  {
436  if ([aDecoder allowsKeyedCoding])
437  {
438  runsInModalSession = [aDecoder decodeBoolForKey:
439  @"WKRunsInModalSessionFlag"];
440  runsInModalSession = [aDecoder decodeBoolForKey:
441  @"WKCentersBeforeActivatingFlag"];
442 
443  ASSIGN(stages, [aDecoder decodeObjectForKey: @"WKStages"]);
444  ASSIGN(initialStage, [aDecoder
445  decodeObjectForKey: @"WKInitialStage"]);
446  }
447  else
448  {
449  [aDecoder decodeValueOfObjCType: @encode(BOOL)
450  at: &runsInModalSession];
451  [aDecoder decodeValueOfObjCType: @encode(BOOL)
452  at: &centersBeforeActivating];
453 
454  ASSIGN(stages, [aDecoder decodeObject]);
455  ASSIGN(initialStage, [aDecoder decodeObject]);
456  }
457  }
458 
459  return self;
460 }
461 
462 @end
463 
469 @implementation WKWizardPanel (Private)
470 
476 - (void) setupForStage: (NSString *) aStage
477 {
478  [self setContentView: [[self delegate] wizardPanel: self
479  viewForStage: aStage]];
480  [self setInitialFirstResponder: [[self delegate] wizardPanel: self
481  initialFirstResponderForStage: aStage]];
482 }
483 
484 @end
485 
490 @implementation NSObject (WKWizardPanelDelegate)
491 
506 - (NSView *) wizardPanel: (WKWizardPanel *) sender
507  viewForStage: (NSString *) aStageName
508 {
509  [NSException raise: NSInternalInconsistencyException
510  format: _(@"Wizard delegate %@ didn't override %@."),
511  [self className], NSStringFromSelector(_cmd)];
512 
513  return nil;
514 }
515 
525 - (NSView *) wizardPanel: (WKWizardPanel *) sender
526  initialFirstResponderForStage: (NSString *) aStageName
527 {
528  return nil;
529 }
530 
531 @end
This informal protocol defines what methods the delegate of a wizard panel may or must implement to c...
Definition: WKWizardPanel.h:65
A wizard panel class.
Definition: WKWizardPanel.h:27
NSString * initialStage
Returns the receiver's initial stage.
Definition: WKWizardPanel.h:35
unsigned int currentStage
Returns the current stage which the receiver displays.
Definition: WKWizardPanel.h:36
BOOL isActive
Returns whether the receiver is active or not.
Definition: WKWizardPanel.h:31
NSArray * stages
Returns a list of stages of the receiver.
Definition: WKWizardPanel.h:34
BOOL centersBeforeActivating
Returns whether the receiver centers itself before activating.
Definition: WKWizardPanel.h:30
BOOL runsInModalSession
Returns whether the receiver activates itself in a modal session.
Definition: WKWizardPanel.h:29