|
|
1.1 root 1: // Thinker.m
2: //
3: // This class is the brains behind the BackSpace app; it is the Application
4: // object's delegate, and it watches the system to determine when to
5: // initiate the screen saver mode.
6: //
7: // You may freely copy, distribute, and reuse the code in this example.
8: // NeXT disclaims any warranty of any kind, expressed or implied, as to its
9: // fitness for any particular use.
10:
11:
12: #import "Thinker.h"
13: #import "BackWindow.h"
14: #import "BackView.h"
15: #import "SpaceView.h"
16: #import "MySlider.h"
17: #import "Password.h"
18: #import "psfuncts.h"
19:
20: #import <appkit/appkit.h>
21: #import <objc/NXBundle.h>
22:
23: // convert vertical blank time to milliseconds
24: #define SEC2MS(x) ((x * 1000) + 20)
25:
26: //#define SHOWITERATIONSPERSEC
27:
28: #ifdef SHOWITERATIONSPERSEC
29: unsigned iterations;
30: BStimeval then, now, targetTime;
31: #endif
32:
33: static id _BSThinker;
34:
35: id BSThinker()
36: { return _BSThinker;
37: }
38:
39:
40: @implementation Thinker
41:
42: - appDidInit:sender
43: {
44: const char *autoLaunch;
45: globalTier = BACKGROUNDTIER;
46: openAnother = YES;
47: _BSThinker = self;
48:
49: backZone = NXCreateZone(vm_page_size, vm_page_size, YES);
50:
51: NXSetRect(&windowRect, 475, 300, 500, 450);
52:
53: [NXApp getScreens:&screens count:&screenCount];
54:
55: [commonImageInspector getFrame: &inspectorFrame];
56: currentInspector = commonImageInspector;
57:
58: [self getViewType];
59: [self setVirtualViewIndexAndIncrement:NO];
60: [self getWindowType];
61:
62: [self getScreenSaverSetting];
63: [self getScreenLockerSetting];
64: [self getPrioritySetting];
65: [self getImageFile];
66: [self getHotCornerSetting];
67:
68: autoLaunch = NXGetDefaultValue([NXApp appName], "NXAutoLaunch");
69: if (strcmp(autoLaunch,"YES"))
70: {
71: [[windMatrix window] makeKeyAndOrderFront:self];
72: windowHasBeenDisplayed = YES;
73: }
74: else [NXApp hide:self];
75:
76: #ifdef SHOWITERATIONSPERSEC
77: then = currentTimeInMs();
78: targetTime = then + 10000;
79: #endif
80:
81: srandom(time(0));
82:
83: return self;
84: }
85:
86: - appDidHide:sender
87: {
88: if (windowType != BACKWINDOW) [self removeTimer];
89: return self;
90: }
91:
92: - appDidUnhide:sender
93: {
94: if (!windowHasBeenDisplayed)
95: {
96: [[windMatrix window] makeKeyAndOrderFront:self];
97: windowHasBeenDisplayed = YES;
98: }
99:
100: if (windowType != NOWINDOW) [self createTimer];
101: return self;
102: }
103:
104:
105:
106: // Pretty much a dummy function to invoke the step method.
107:
108: void timedEntryFunction (DPSTimedEntry timedEntry, double timeNow, void *theObject)
109: { [(id)theObject doDistributorLoop];
110: }
111:
112: - createTimer
113: {
114: if (!timerValid)
115: {
116: timerValid = YES;
117: timer = DPSAddTimedEntry(0.02, &timedEntryFunction, self, NX_BASETHRESHOLD);
118: }
119: return self;
120: }
121:
122: - removeTimer
123: {
124: if (timerValid) DPSRemoveTimedEntry (timer);
125: timerValid = NO;
126: return self;
127: }
128:
129: - doDistributorLoop
130: {
131: NXEvent dummyEvent;
132:
133: keepLooping = YES;
134: [spaceView lockFocus];
135: if ([spaceView respondsTo:@selector(didLockFocus)]) [spaceView didLockFocus];
136:
137: do {
138: [spaceView oneStep];
139: [spaceWindow flushWindow];
140: NXPing (); // Synchronize postscript for smoother animation
141:
142: [spaceView oneStep];
143: [spaceWindow flushWindow];
144: NXPing (); // Synchronize postscript for smoother animation
145:
146: #ifdef SHOWITERATIONSPERSEC
147: iterations++;
148: if ((now = currentTimeInMs()) > targetTime)
149: {
150: printf("BackSpace: %5.1f its/sec\n",
151: (double)iterations*1000.0/(double)(now - then));
152: iterations = 0;
153: targetTime = now + 10000;
154: then = now;
155: }
156: #endif
157:
158: } while (timerValid && keepLooping &&
159: ([NXApp peekNextEvent:NX_ALLEVENTS into:&dummyEvent
160: waitFor:0 threshold:NX_BASETHRESHOLD] == NULL));
161:
162: [spaceView unlockFocus];
163:
164: return self;
165:
166: }
167:
168: - installSpaceViewIntoWindow:w
169: {
170: NXRect cvrect;
171: int i;
172: id subviews, contentView;
173:
174: if (!w) return nil;
175: contentView = [w contentView];
176:
177: // get size of content view
178: [contentView getBounds:&cvrect];
179:
180: // remove old subviews, this is overkill really...
181: subviews = [contentView subviews];
182: for (i=([subviews count]-1); i>=0; i--)
183: { [[subviews objectAt:i] removeFromSuperview];
184: }
185:
186: // install it into the window's content view
187: [contentView addSubview:spaceView];
188: [contentView setAutoresizeSubviews:YES];
189: [spaceView setAutosizing:NX_WIDTHSIZABLE | NX_HEIGHTSIZABLE];
190:
191: // size the spaceview
192: [spaceView sizeTo:cvrect.size.width :cvrect.size.height];
193:
194: return self;
195: }
196:
197: - useNormalWindow
198: {
199: int myBacking;
200:
201: spaceView = [self backView];
202: myBacking = [self backingTypeForView:spaceView];
203:
204: if (!normalWindow)
205: {
206: normalWindow = [[Window allocFromZone:backZone]
207: initContent:&windowRect style:NX_RESIZEBARSTYLE
208: backing:myBacking
209: buttonMask:NX_CLOSEBUTTONMASK
210: defer:NO];
211:
212: [self setWindowTitle];
213: [normalWindow useOptimizedDrawing:YES];
214: [normalWindow setDynamicDepthLimit:YES]; //want window depth to match device!
215: [normalWindow setOneShot:YES];
216: [normalWindow setDelegate:self];
217: [normalWindow setBackgroundGray:NX_BLACK];
218: }
219:
220: spaceWindow = normalWindow;
221: [self installSpaceViewIntoWindow:spaceWindow];
222:
223: if ([spaceView respondsTo:@selector(setImage:)])
224: [spaceView setImage: image];
225: if ([spaceView respondsTo:@selector(newWindow)]) [spaceView newWindow];
226: [spaceWindow display];
227:
228: [spaceWindow makeKeyAndOrderFront:self];
229:
230: // need to do this so flushing always works!
231: // must do it late because kit does lazy window creation ie the PostScript
232: // window might not exist until you actually draw to it
233:
234: if (myBacking == NX_RETAINED)
235: [spaceWindow setBackingType:NX_RETAINED];
236: else [spaceWindow setBackingType:NX_BUFFERED];
237:
238: return self;
239: }
240:
241: - (int) backingTypeForView:aView
242: {
243: if ([aView respondsTo:@selector(useBufferedWindow)]
244: && [aView useBufferedWindow])
245: return NX_BUFFERED;
246: return NX_RETAINED;
247: }
248:
249: - useBackWindow:(int)tier
250: {
251: NXRect r={{0, 0}};
252: int myBacking;
253:
254: [NXApp getScreenSize:&(r.size)];
255:
256: spaceView = [self backView];
257: myBacking = [self backingTypeForView:spaceView];
258:
259: [self createBigWindowIfNecessaryForView:spaceView];
260:
261: if (myBacking == NX_RETAINED)
262: { spaceWindow = bigUnbufferedWindow;
263: tweakWindow([spaceWindow windowNum], tier);
264: }
265: else
266: { spaceWindow = bigBufferedWindow;
267: }
268:
269: [self installSpaceViewIntoWindow:spaceWindow];
270:
271: if ([spaceView respondsTo:@selector(setImage:)])
272: [spaceView setImage: image];
273:
274: [spaceWindow placeWindow:&r];
275: if (myBacking == NX_BUFFERED) [spaceWindow display];
276:
277: [spaceWindow orderFront:self];
278: if (myBacking == NX_BUFFERED) tweakWindow([spaceWindow windowNum], tier);
279: else [spaceWindow display];
280:
281: if ([spaceView respondsTo:@selector(newWindow)]) [spaceView newWindow];
282:
283: return self;
284: }
285:
286: - createBigWindowIfNecessaryForView:aView
287: {
288: NXRect r={{0, 0}};
289: int myBacking = [self backingTypeForView:aView];
290:
291: [NXApp getScreenSize:&(r.size)];
292:
293: if ((myBacking == NX_RETAINED) && !bigUnbufferedWindow)
294: {
295:
296: bigUnbufferedWindow = [[BackWindow allocFromZone:backZone]
297: initContent:&r style:NX_TOKENSTYLE
298: backing:NX_NONRETAINED buttonMask:0 defer:NO];
299:
300: [bigUnbufferedWindow useOptimizedDrawing:YES];
301:
302: [bigUnbufferedWindow removeFromEventMask:(NX_LMOUSEDOWNMASK | NX_LMOUSEUPMASK
303: | NX_MOUSEMOVEDMASK | NX_LMOUSEDRAGGEDMASK
304: | NX_MOUSEENTEREDMASK | NX_MOUSEEXITEDMASK
305: | NX_KEYDOWNMASK | NX_KEYUPMASK
306: | NX_CURSORUPDATEMASK)];
307: [bigUnbufferedWindow setBackgroundGray:NX_BLACK];
308: }
309:
310: if ((myBacking == NX_BUFFERED) && !bigBufferedWindow)
311: {
312:
313: bigBufferedWindow = [[BackWindow allocFromZone:backZone]
314: initContent:&r style:NX_TOKENSTYLE
315: backing:NX_BUFFERED buttonMask:0 defer:NO];
316:
317: [bigBufferedWindow useOptimizedDrawing:YES];
318:
319: [bigBufferedWindow removeFromEventMask:(NX_LMOUSEDOWNMASK | NX_LMOUSEUPMASK
320: | NX_MOUSEMOVEDMASK | NX_LMOUSEDRAGGEDMASK
321: | NX_MOUSEENTEREDMASK | NX_MOUSEEXITEDMASK
322: | NX_KEYDOWNMASK | NX_KEYUPMASK
323: | NX_CURSORUPDATEMASK)];
324:
325: [bigBufferedWindow setDynamicDepthLimit:YES]; //want window depth to match device!
326: [bigBufferedWindow setOneShot:YES];
327: [bigBufferedWindow setBackgroundGray:NX_BLACK];
328: }
329:
330: return self;
331: }
332:
333: - changeWindowType:sender
334: {
335: [self changeWindowTypeAndRemember:YES];
336: return self;
337: }
338:
339: - changeWindowTypeAndRemember:(BOOL)rem
340: {
341: char str[10];
342: int newWindowType;
343:
344: newWindowType = [windMatrix selectedRow];
345: if (newWindowType == windowType) return self;
346:
347: windowType = newWindowType;
348:
349: if (rem)
350: {
351: sprintf(str,"%1d", windowType);
352: NXWriteDefault([NXApp appName], "windowType", str);
353: }
354:
355: [spaceWindow orderOut:self];
356:
357: switch (windowType)
358: {
359: case NOWINDOW:
360: [self removeTimer];
361: break;
362: case NORMALWINDOW:
363: [self useNormalWindow];
364: [self createTimer];
365: break;
366: case BACKWINDOW:
367: [self useBackWindow: globalTier];
368: [self createTimer];
369: break;
370: }
371:
372: return self;
373: }
374:
375: - getWindowType
376: {
377: int tWindowType = NORMALWINDOW;
378: const char *ptr;
379: int val;
380:
381: ptr = NXGetDefaultValue([NXApp appName], "windowType");
382: if (ptr)
383: {
384: sscanf(ptr,"%d",&val);
385: if (val >= 0 && val <= 2) tWindowType = val;
386: }
387:
388: [windMatrix selectCellAt:tWindowType :0];
389: [self changeWindowTypeAndRemember:NO];
390:
391: return self;
392: }
393:
394: - getScreenSaverSetting
395: {
396: const char *ptr;
397:
398: if((evs = NXOpenEventStatus()) == 0)
399: { perror("NXOpenEventStatus failed.");
400: exit(10);
401: }
402:
403: [self getDimBrightness:&dimBrightness];
404:
405: //in case the old dim brightness is somehow invalid, I reset it
406: if (dimBrightness > .25)
407: {
408: dimBrightness = .25;
409: [self _setDimBrightness:&dimBrightness];
410: }
411:
412: [screenSaver setState:0];
413:
414: ptr = NXGetDefaultValue([NXApp appName], "screenSaver");
415:
416: if (!ptr || !strcmp(ptr,"Off")) [self setScreenSaver:NO andRemember:NO];
417: else [self setScreenSaver:YES andRemember:NO];
418:
419: return self;
420: }
421:
422: - changeScreenSaverSetting:sender
423: {
424: [self setScreenSaver:([screenSaver state])andRemember:YES];
425: return self;
426: }
427:
428: - setScreenSaver:(BOOL)val andRemember:(BOOL)rem
429: {
430: [screenSaver setState:val];
431: screenSaverVal = val;
432:
433: if (val)
434: {
435: // turn it on...
436: [self calcDimTime];
437: if (rem) NXWriteDefault([NXApp appName], "screenSaver", "On");
438: }
439: else
440: {
441: // turn it off...
442: if (rem) NXRemoveDefault([NXApp appName], "screenSaver");
443: }
444:
445: return self;
446: }
447:
448: - calcDimTime
449: {
450: double dimTime;
451: [self getDimTime :&dimTime];
452:
453: if (dimTime < 0) dimTime = .1;
454:
455: if (screenSaverVal && !doingSaver)
456: {
457: // printf("BackSpace calcDimTime: dims in %f seconds\n",dimTime);
458:
459: [self perform:@selector(maybeDoScreenSaver:)
460: with:self
461: afterDelay:SEC2MS(dimTime)
462: cancelPrevious:YES];
463: }
464:
465: return self;
466: }
467:
468: - maybeDoScreenSaver:sender
469: {
470: NXEvent anEvent;
471: BOOL autoDimmed;
472:
473: // in case timed entry fires but user has killed screen saver
474: if (!screenSaverVal || doingSaver) return self;
475:
476: autoDimmed = NXAutoDimState(evs);
477: if (!autoDimmed)
478: {
479: [self calcDimTime];
480: return self;
481: }
482:
483: // The perform:afterDelay: method starts a timed entry to
484: // invoke maybeDoScreenSaver, so we are in a timed entry
485: // right now. If we just jumped into doScreenSaver:, we
486: // would interrupt the doDistributorLoop method while
487: // it's still focused on the spaceView. By posting an
488: // event, we force that loop to bail out so we can jump
489: // into the screen saver cleanly.
490:
491: keepLooping = NO; // There was a bug related to this at one point.
492: // I don't think it's necessary anymore.
493: anEvent.type = NX_APPDEFINED;
494: anEvent.data.compound.subtype = BSDOSAVER;
495: anEvent.ctxt = [NXApp context];
496: DPSPostEvent(&anEvent,0);
497:
498: return self;
499: }
500:
501: - applicationDefined:(NXEvent *)theEvent
502: {
503: switch (theEvent->data.compound.subtype)
504: {
505: case BSDOSAVER:
506: [self doScreenSaver:self];
507: [self calcDimTime]; // reset to fire again
508: break;
509: case BSOPENFILE:
510: [self doDelayedOpenFile];
511: break;
512: default:
513: break;
514: }
515: return self;
516: }
517:
518: - showFakeScreenSaverAfterPause:sender
519: {
520: usleep(250000);
521: return [self showFakeScreenSaver:sender];
522: }
523:
524: - showFakeScreenSaver:sender
525: {
526: [self screenSaverMode];
527: NXSetAutoDimState(evs, YES);
528: [self doScreenSaver:self];
529: NXSetAutoDimState(evs, NO);
530: [self normalMode]; //usually not necessary
531:
532: // reset to fire again
533: [self calcDimTime];
534:
535: return self;
536: }
537:
538:
539: - doScreenSaver:sender
540: {
541: BOOL autoDimmed;
542: int oldWindowType;
543: BOOL mouseOK, oldTimerValid;
544: BOOL ignoreMouseMovement = NO;
545: BOOL isHidden;
546: NXRect trackingRect;
547: NXPoint mouseLoc;
548: BOOL passwordOK;
549: BOOL stoleActivation = NO;
550: int oldActiveApp = 0;
551: int iterationCount = 0;
552:
553: // must be sure we don't enter on timed entry after faking saver
554: doingSaver = YES;
555:
556: isHidden = [NXApp isHidden];
557: if (isHidden)
558: {
559: [NXApp unhideWithoutActivation:self];
560: }
561:
562: // force activation here so we get keystrokes if someone
563: // just types his password.
564: if ([password isLocked])
565: {
566: oldActiveApp = [NXApp activateSelf:YES];
567: stoleActivation = YES;
568: }
569:
570: [self setVirtualViewIndexAndIncrement:YES];
571:
572: //save old window state
573: oldWindowType = [windMatrix selectedRow];
574:
575: globalTier = SAVERTIER;
576:
577: [self blackOutAllScreens];
578:
579: //background window on screen
580: [windMatrix selectCellAt:BACKWINDOW :0];
581: [self changeWindowTypeAndRemember:NO];
582:
583: //nuke timer so timed entry doesn't fire
584: oldTimerValid = timerValid;
585: [self removeTimer];
586:
587:
588: //set background window tier to SAVERTIER
589: if ([self backingTypeForView:spaceView] == NX_BUFFERED)
590: {
591: // make sure the one shot buffer really exists
592: //[spaceWindow display]; //xxx
593: if ([spaceWindow windowNum] <= 0) [spaceWindow display];
594: PSsetwindowlevel(SAVERTIER, [spaceWindow windowNum]);
595: }
596: else
597: {
598: PSsetwindowlevel(SAVERTIER, [spaceWindow windowNum]);
599: [spaceView fillBoundsWithBlack];
600: [spaceView display];
601: }
602:
603: NXPing();
604: [self screenSaverMode];
605:
606: PSsetwaitcursorenabled(NO);
607:
608: if ([spaceView respondsTo:@selector(enteredScreenSaverMode)])
609: [spaceView enteredScreenSaverMode];
610:
611: do {
612: //obscure cursor
613: PSobscurecursor();
614:
615: [spaceView lockFocus];
616: if ([spaceView respondsTo:@selector(didLockFocus)])
617: [spaceView didLockFocus];
618:
619:
620: if ([spaceView respondsTo:@selector(ignoreMouseMovement)])
621: ignoreMouseMovement = [spaceView ignoreMouseMovement];
622:
623: [spaceWindow getMouseLocation:&mouseLoc];
624: trackingRect.origin.x = mouseLoc.x - 100;
625: trackingRect.origin.y = mouseLoc.y - 100;
626: trackingRect.size.width = trackingRect.size.height = 200;
627:
628: do {
629: if ((++iterationCount & 0x7f)==0) PSobscurecursor();
630:
631: [spaceView oneStep];
632: [spaceWindow flushWindow];
633: NXPing(); // Synchronize postscript for smoother animation
634:
635: // note: window and view coordinates the same!
636: // so I don't have to convert to view coord system
637: if (ignoreMouseMovement) mouseOK = YES;
638: else
639: {
640: [spaceWindow getMouseLocation:&mouseLoc];
641: mouseOK = [spaceView mouse:&mouseLoc inRect:&trackingRect];
642: }
643:
644: [spaceView oneStep];
645: [spaceWindow flushWindow];
646: NXPing(); // Synchronize postscript for smoother animation
647:
648: autoDimmed = NXAutoDimState(evs);
649: } while (autoDimmed && mouseOK);
650:
651: [spaceView unlockFocus];
652:
653: // force activation here in case anyone changed it out
654: // from under me. (workspace does this, dog gone it!)
655: if ([password isLocked])
656: {
657: [NXApp activateSelf:YES];
658: }
659:
660: passwordOK = [password checkPassword:
661: NXLocalString("Screen is locked. Enter password to unlock:",0,0)
662: randomPos:YES checkLock:YES withView:spaceView];
663:
664: if (!passwordOK) NXSetAutoDimState(evs, YES);
665:
666: } while (!passwordOK);
667:
668: if ([spaceView respondsTo:@selector(willExitScreenSaverMode)])
669: [spaceView willExitScreenSaverMode];
670:
671: NXSetAutoDimState(evs, NO);
672:
673: PSsetwaitcursorenabled(YES);
674:
675: [self normalMode];
676:
677: //background window tier to BACKGROUNDTIER
678: PSsetwindowlevel(BACKGROUNDTIER, [spaceWindow windowNum]);
679: globalTier = BACKGROUNDTIER;
680:
681: if (([self backingTypeForView:spaceView] != NX_BUFFERED) &&
682: oldWindowType == BACKWINDOW)
683: // this justs fixes a display bug for really lazy nonretained windows
684: {
685: [spaceView fillBoundsWithBlack];
686: [spaceView display];
687: }
688:
689: if (oldTimerValid) [self createTimer];
690:
691: [self unBlackOutAllScreens];
692:
693: //restore old window state
694: [windMatrix selectCellAt:oldWindowType :0];
695: [self changeWindowTypeAndRemember:NO];
696:
697: if (stoleActivation)
698: {
699: if (oldActiveApp) [NXApp activate:oldActiveApp];
700: else [NXApp deactivateSelf];
701: }
702:
703: if (isHidden)
704: {
705: [NXApp hide:self];
706: }
707:
708: doingSaver = NO;
709:
710: return self;
711: }
712:
713: - appWillTerminate:sender
714: {
715: [self normalMode];
716: return self;
717: }
718:
719: - appDidBecomeActive:sender
720: {
721: id theMatrix;
722:
723: theMatrix = [viewSelectionBrowser matrixInColumn:0];
724: [theMatrix scrollCellToVisible:realViewIndex :0];
725: return self;
726: }
727:
728: - app:sender powerOffIn:(int)ms andSave:(int)aFlag
729: {
730: return [NXApp terminate:self];
731: }
732:
733: - getPrioritySetting
734: {
735: const char *ptr;
736: int val;
737:
738: [mySlider setMinValue: 0];
739: [mySlider setMaxValue: 10];
740:
741: ptr = NXGetDefaultValue([NXApp appName], "priority");
742: if (ptr)
743: {
744: sscanf(ptr,"%d",&val);
745: if (val >= 0 && val <= 10) priority = val;
746: else priority = 4;
747: }
748: else priority = 4;
749:
750: [[mySlider cell] setIntValue:priority];
751: [[priorityLevel cell] setIntValue:priority];
752:
753: // use mach call rather than unix - mach lets me increase priority!
754: // setpriority(PRIO_PROCESS, 0, priority);
755: cthread_priority(cthread_self(), priority, FALSE);
756:
757: return self;
758: }
759:
760: - changeSliderValue:sender
761: {
762: priority = [[mySlider cell] intValue];
763: [[priorityLevel cell] setIntValue:priority];
764: return self;
765: }
766:
767: - saveSliderValue
768: {
769: char str[50];
770: // setpriority(PRIO_PROCESS, 0, priority);
771: cthread_priority(cthread_self(), priority, FALSE);
772:
773: sprintf(str,"%d", priority);
774: NXWriteDefault([NXApp appName], "priority", str);
775: return self;
776: }
777:
778: - windowWillResize:sender toSize:(NXSize *)frameSize
779: {
780: if (frameSize->width < 100) frameSize->width = 100;
781: if (frameSize->height < 100) frameSize->height = 100;
782: return self;
783: }
784:
785: - windowWillClose:sender
786: {
787: [windMatrix selectCellAt:NOWINDOW :0];
788: [self perform:@selector(changeWindowType:) with:self
789: afterDelay:1 cancelPrevious:YES];
790: return nil;
791: }
792:
793: BStimeval currentTimeInMs()
794: {
795: struct timeval curTime;
796: gettimeofday (&curTime, NULL);
797: return (curTime.tv_sec) * 1000 + curTime.tv_usec / 1000;
798: }
799:
800: //
801: // Additional methods to handle a common image object for views.
802: // Lennart Lovstrad, Rank Xerox EuroPARC, August 1991.
803: //
804:
805: - setImageFromFile: (const char *) filename
806: {
807: [image free];
808:
809: image = [[NXImage alloc] initFromFile: filename];
810: if (image == nil)
811: {
812: NXRunAlertPanel([NXApp appName], NXLocalString("Could not open %s",0,0),
813: NULL, NULL, NULL, filename);
814: image = nil;
815: //return nil; //can't return, image is invalid
816: }
817:
818: return [self commonImageInit];
819: }
820:
821: - setImageFromName: (const char *) name
822: {
823: [image free];
824: image = [[NXImage alloc] initFromSection: name];
825:
826: return [self commonImageInit];
827: }
828:
829: - commonImageInit
830: {
831: [imageView setImage: image];
832: [imageView display];
833:
834: if ([spaceView respondsTo:@selector(setImage:)])
835: [spaceView setImage: image];
836:
837: if ([self backingTypeForView:spaceView] != NX_BUFFERED)
838: {
839: [spaceView fillBoundsWithBlack];
840: [spaceView display];
841: }
842:
843: return self;
844: }
845:
846: - getImageFile
847: {
848: const char *filename;
849:
850: filename = NXGetDefaultValue([NXApp appName], "imageFile");
851: if (filename)
852: [self setImageFromFile: filename];
853: else [self setImageFromName: "defaultImage"];
854:
855: return self;
856: }
857:
858: - setImageFileFrom: sender
859: {
860: id openPanel = [OpenPanel new];
861: const char *fileTypes[] = {"tiff", "eps", NULL};
862:
863: if ([openPanel runModalForTypes: fileTypes])
864: {
865: [self setImageFromFile: [openPanel filename]];
866: NXWriteDefault([NXApp appName], "imageFile", [openPanel filename]);
867: }
868:
869: [spaceView display]; //don't know why this is necessary...
870:
871: return self;
872: }
873:
874: // This should return a float between 0 and 1
875: float frandom()
876: {
877: float val = (random() & 0x7fffffff);
878: val /= 0x7fffffff;
879: return val;
880: }
881:
882: float randBetween(float a, float b)
883: {
884: float val, scale, t;
885:
886: if (a > b)
887: { t = a; a = b; b = t;
888: }
889:
890: scale = (b-a);
891: val = scale * frandom();
892: return (a + val);
893: }
894:
895: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.