4 Created by falkenst on Tue Feb 08 2005.
5 Copyright (c) 2005 jan truetzschler. All rights reserved.
7 SuperCollider real time audio synthesis system
8 Copyright (c) 2002 James McCartney. All rights reserved.
9 http://www.audiosynth.com
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <Cocoa/Cocoa.h>
28 #include <Carbon/Carbon.h>
32 #include "PyrPrimitive.h"
33 #include "PyrObject.h"
34 #include "PyrKernel.h"
36 #include "VMGlobals.h"
38 #include "SC_BoundsMacros.h"
39 #include "SC_InlineBinaryOp.h"
40 #include "PyrListPrim.h"
43 #include "SCCocoaView.h"
44 #include "QTKit/QTKit.h"
45 #import "HTMLRenderer.h"
46 #import "MyDocument.h"
50 extern pthread_mutex_t gLangMutex
;
51 extern bool compiledOK
;
54 extern PyrSymbol
*s_scimage
; // class symbol
55 extern PyrObject
* newPyrSCImage(VMGlobals
* g
); // class creation func
57 void SyntaxColorize(NSTextView
* textView
);
59 static NSString
*sSCObjType
= @
"SuperCollider object address";
60 extern PyrSymbol
*s_scview
;
62 @implementation SCCocoaTextViewResponder
64 - (struct PyrObject
*)getSCObject
66 return mSCViewObject
->GetSCObj();
68 - (void)textDidEndEditing
:(NSNotification
*)aNotification
70 // post("endEditing");
72 - (void)textDidBeginEditing
:(NSNotification
*)aNotification
76 - (void)setSCView
: (class SCCocoaTextView
*)inObject
78 mSCViewObject
= inObject
;
82 - (IBAction
) executeSelection
: (id) sender
84 if(enterExecutesSelection
)
85 [self sendSelection
: @
"interpretPrintCmdLine" ];
88 - (void)sendSelection
: (NSString
*) nsmethodName
93 const char *methodName
= [nsmethodName UTF8String
];
94 NSRange selectedRange
;
95 SCTextView
* txtView
= mSCViewObject
->getTextView();
96 NSString
* selection
= [txtView currentlySelectedTextOrLine
: &selectedRange
];
97 const char *text
= [selection UTF8String
];
98 int textlength
= strlen(text
);
100 [[SCVirtualMachine sharedInstance
] setCmdLine
: text length
: textlength
];
102 NSRange newSelectedRange
= NSMakeRange(selectedRange.location
+ selectedRange.length
, 0);
103 [txtView setSelectedRange
: newSelectedRange
];
105 pthread_mutex_lock(&gLangMutex
);
106 runLibrary(getsym(methodName
));
107 pthread_mutex_unlock(&gLangMutex
);
111 //- (void) keyDown: (NSEvent*) event
112 //- (BOOL)textView:(NSTextView *)textView shouldChangeTextInRanges:(NSArray *)affectedRanges replacementStrings:(NSArray *)characters
113 - (BOOL) handleKeyDown
: (NSEvent
*) event
;
116 // for some reason modifiers becomes 256 on my machine with no keys pressed. So need to mask against known keys.
117 if(usesTabToFocusNextView
&& ([event type
] == NSKeyDown
)){
118 NSString
*characters
= [event characters
];
119 unsigned int modifiers
= [event modifierFlags
];
120 uint32 allKnownModifiers
= NSAlphaShiftKeyMask | NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask
121 | NSAlternateKeyMask | NSHelpKeyMask | NSFunctionKeyMask
;
122 unichar character
= 0;
123 if([characters length
] > 0) {
124 character
= [characters characterAtIndex
: 0];
126 if(character
== 9 && ((modifiers
& allKnownModifiers
) == 0)) {
127 mSCViewObject
->tabPrevFocus();
129 } else if (character
== 25 && ((modifiers
& allKnownModifiers
) == NSShiftKeyMask
)) { // check above for tab
131 /////[mSCViewObject->getTextView() resignFirstResponder];
132 mSCViewObject
->tabNextFocus();
134 } // other tab keys avail for user
139 //- (BOOL) handleKeyDown: (NSEvent*) event;
141 // //NSLog(@"keyDown");
142 // // for some reason modifiers becomes 256 on my machine with no keys pressed. So need to mask against known keys.
143 // if(usesTabToFocusNextView){
144 // NSString *characters = [event characters];
145 // unsigned int modifiers = [event modifierFlags];
146 // uint32 allKnownModifiers = NSAlphaShiftKeyMask | NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask
147 // | NSAlternateKeyMask | NSHelpKeyMask | NSFunctionKeyMask;
148 // unichar character = 0;
149 // if([characters length] > 0) {
150 // character = [characters characterAtIndex: 0];
151 // //NSLog(@"char %i", character);
153 // if (character == 25 && ((modifiers & allKnownModifiers) == NSShiftKeyMask)) { // check above for tab
154 // //NSLog(@"backtab");
155 // /////[mSCViewObject->getTextView() resignFirstResponder];
156 // mSCViewObject->tabNextFocus();
158 // } // other tab keys avail for user
162 - (void) keyUp
: (NSEvent
*) event
166 - (void) mouseDown
: (NSEvent
*) event
168 mSCViewObject
->makeFocus(true);
171 - (void) setUsesTabToFocusNextView
: (BOOL) flag
173 usesTabToFocusNextView
= flag
;
176 - (void) setEnterExecutesSelection
: (BOOL) flag
178 enterExecutesSelection
= flag
;
181 - (BOOL) textView
: (NSTextView
*) textView
182 clickedOnLink
: (id) link
183 atIndex
: (unsigned) charIndex
185 bool loadLinkInView
= mSCViewObject
->getLoadLinkInView();
186 NSDocumentController
* docctl
= [NSDocumentController sharedDocumentController
];
187 if (!docctl
&& !loadLinkInView
) return YES
;
191 // is it a NSURL link or a NSString link?
192 if ([link isKindOfClass
: [NSString
class]])
194 if([link hasPrefix
:@
"SC://"] ||
[link hasPrefix
:@
"sc://"]) { // this means search immediately
195 NSString
*helpPath
= pathOfHelpFileFor([[[link substringFromIndex
:5] stringByDeletingPathExtension
] stringByDeletingPathExtension
]);
197 post("WARNING:\nInvalid hyperlink: '%s' Please repair this.\n", [link cStringUsingEncoding
:[NSString defaultCStringEncoding
]]);
200 desiredURL
= [NSURL URLWithString
: helpPath
];
201 } else desiredURL
= [NSURL URLWithString
: [link stringByAddingPercentEscapesUsingEncoding
: NSUTF8StringEncoding
] relativeToURL
: mSCViewObject
->getLastURL()];
203 } else if ([link isKindOfClass
: [NSURL
class]])
205 // check for schemes which we'll handle
206 if([[link scheme
] isEqualToString
: @
"SC"] ||
[[link scheme
] isEqualToString
:@
"sc"]) { // this means search immediately
207 NSString
*helpPath
= pathOfHelpFileFor([[[[link relativeString
] substringFromIndex
:5] stringByDeletingPathExtension
] stringByDeletingPathExtension
]);
209 post("WARNING:\nInvalid hyperlink: '%s' Please repair this.\n", [[link relativeString
] cStringUsingEncoding
:[NSString defaultCStringEncoding
]]);
212 desiredURL
= [NSURL fileURLWithPath
: helpPath
];
213 } else if (![link scheme
]) { // NULL could be a regular file link that's been edited
214 if([[link relativePath
] hasPrefix
: @
"/"]) {
215 desiredURL
= [NSURL fileURLWithPath
: [link relativeString
]];
217 desiredURL
= [NSURL URLWithString
: [[link relativeString
] stringByAddingPercentEscapesUsingEncoding
: NSUTF8StringEncoding
] relativeToURL
: mSCViewObject
->getLastURL()];
219 } else if(![[link scheme
] isEqualToString
: @
"file"]) {
220 return NO
; // it's http, etc. so pass it on to Safari or whatever
222 desiredURL
= link
; // it's a regular file:// URL
226 // try the link action first then use default
227 if(mSCViewObject
->linkAction([desiredURL absoluteString
])) return YES
;
229 MyDocument
*doc
= nil;
232 if([[NSFileManager defaultManager
] fileExistsAtPath
: [desiredURL path
]]) {
233 if(!loadLinkInView
) doc
= (MyDocument
*)[docctl documentForURL
: [desiredURL absoluteURL
]];
234 } else NSLog(@
"file doesn't exist at path");
236 if(!loadLinkInView
) {
237 doc
= [docctl openDocumentWithContentsOfURL
: desiredURL display
: true];
239 result
= mSCViewObject
->open([desiredURL path
]);
241 if (!doc
&& result
) {
242 // it's a bad file:// URL, post a warning and search
243 post("WARNING:\nInvalid hyperlink: '%s' Please repair this.\nSearching help directories for alternative.\n", [[desiredURL path
] cStringUsingEncoding
:[NSString defaultCStringEncoding
]]);
244 // delete extension twice in case something.help.rtf
245 NSString
*desiredHelpName
= [[[[desiredURL path
] lastPathComponent
] stringByDeletingPathExtension
] stringByDeletingPathExtension
];
246 NSString
*helpPath
= pathOfHelpFileFor(desiredHelpName
);
248 post("Can't find Help File Document for: '%s'\n", [desiredHelpName cStringUsingEncoding
:[NSString defaultCStringEncoding
]]);
251 desiredURL
= [NSURL fileURLWithPath
: helpPath
];
252 if([[NSFileManager defaultManager
] fileExistsAtPath
: [desiredURL path
]]) {
253 if(!loadLinkInView
) {
254 doc
= (MyDocument
*)[docctl documentForURL
: [desiredURL absoluteURL
]];
256 } else post("file doesn't exist at path: '%s'\n", [[desiredURL path
] cStringUsingEncoding
:[NSString defaultCStringEncoding
]]);
258 if(!loadLinkInView
) {
259 doc
= [docctl openDocumentWithContentsOfURL
: desiredURL display
: true];
261 result
= mSCViewObject
->open(helpPath
);
264 post("Can't open Help File Document: '%s'\n", [[desiredURL path
] cStringUsingEncoding
:[NSString defaultCStringEncoding
]]);
270 if(!loadLinkInView
) {
271 NSWindow
*window
= [[[doc windowControllers
] objectAtIndex
: 0] window
];
273 post("!! window controller returns nil ? failed to open help file window\n");
276 [window makeKeyAndOrderFront
: nil];
281 - (void) loadHTMLToTextView
:(NSURL
*)url
284 SCTextView
*textView
= mSCViewObject
->getTextView();
285 NSTextStorage
* text
= [textView textStorage
];
286 [text beginEditing
]; // Bracket with begin/end editing for efficiency
288 NSAttributedString
*htmlAttributedString
= [HTMLRenderer attributedStringWithURL
:url
];
290 if(htmlAttributedString
)
292 [text setAttributedString
:htmlAttributedString
];
293 [textView setDefaultTabsTo
: 28.0f
];
300 // for compatibility with Document
301 - (void)setActiveTextView
:(SCTextView
*)aTextView
307 @implementation SCTextFieldResponder
309 //- (id)initWithFrame:(NSRect)frameRect
311 // backGroundColor = [[NSColor whiteColor] retain];
312 // return [super initWithFrame:frameRect];
317 // [backGroundColor release];
321 //- (void)setBackgroundColor:(NSColor *)aColor
324 // [backGroundColor release];
325 // backGroundColor = aColor;
328 //- (void)drawRect:(NSRect)aRect
330 // // draw a background
331 // CGContextRef cgc = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
332 // CGContextSaveGState(cgc);
333 // CGContextSetRGBFillColor(cgc, 1.0, 0.0, 0.0, 0.5);
334 // CGContextFillRect(cgc, (*(CGRect *)&(aRect)));
335 // CGContextRestoreGState(cgc);
337 // [super drawRect:aRect]; // call superclass here for everything else
340 - (struct PyrObject
*)getSCObject
342 return mSCViewObject
->GetSCObj();
345 //- (void)controlTextDidEndEditing:(NSNotification *)aNotification
347 // if(textReallyChanged){
348 // pthread_mutex_lock (&gLangMutex);
349 // PyrSymbol *method = getsym("doAction");
351 // if (mObj = mSCViewObject->GetSCObj()) {
352 // VMGlobals *g = gMainVMGlobals;
353 // g->canCallOS = true;
354 // ++g->sp; SetObject(g->sp, mObj);
355 // runInterpreter(g, method, 1);
356 // g->canCallOS = false;
358 // pthread_mutex_unlock (&gLangMutex);
359 // textReallyChanged = false;
364 //- (BOOL)textShouldBeginEditing:(NSText *)fieldEditor
367 // if(mSCViewObject->isFocus()) return YES;
372 //- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
374 // //[(SCFieldEditor*)fieldEditor setCurrentTextField:self];
379 //- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
381 // //[(SCFieldEditor*)fieldEditor setCurrentTextField:nil];
386 //- (void)mouseDown:(NSEvent *)theEvent
389 // mSCViewObject->makeFocus(true);
390 // unsigned int modifiers = [theEvent modifierFlags];
391 // //control tab/escape doesn't get passed here at all ?
392 // if(modifiers & NSCommandKeyMask) {
393 // [self selectText:self]; // exit editing and select all for a drag
395 // } else [super mouseDown:theEvent];
398 //- (void)drawRect:(NSRect)aRect
400 // [backGroundColor setFill];
401 // NSRectFill(aRect);
402 // [super drawRect:aRect];
405 -(void)rightMouseDown
:(NSEvent
*)theEvent
{ [self mouseDown
:theEvent
]; }
406 -(void)otherMouseDown
:(NSEvent
*)theEvent
{ [self mouseDown
:theEvent
]; }
407 - (void)mouseDown
:(NSEvent
*)theEvent
409 //NSLog(@"SCGraphView MOUSEDOWN");
410 //[[self window] makeFirstResponder:self]; // there may be an active field editor
412 //BOOL isInside = YES;
414 //NSLog(@"Click count: %i", [theEvent clickCount]);
415 //if([theEvent clickCount] == 2) return;
416 //if (!mTopView) return;
417 unsigned int modifiers
= [theEvent modifierFlags
];
418 mouseLoc
= [self convertPoint
:[theEvent locationInWindow
] fromView
:nil];
419 SCPoint scpoint
= SCMakePoint(mouseLoc.x
, mouseLoc.y
);
420 SCTopView
*mTopView
= mSCViewObject
->getTop();
423 bool mouseMoved
= NO
;
425 mSCViewObject
->makeFocus(true);
426 // force focus ring into drawing even if we're already in focus
427 SEL sel
= @selector(setNeedsDisplay
:);
428 NSMethodSignature
*sig
= [NSView instanceMethodSignatureForSelector
: sel
];
429 NSInvocation
*anInvocation
= [NSInvocation invocationWithMethodSignature
: sig
];
430 SCVirtualMachine
* scvm
= [SCVirtualMachine sharedInstance
];
431 [anInvocation setTarget
: [self superview
]];
432 [anInvocation setSelector
: sel
];
434 [anInvocation setArgument
: &flag atIndex
: 2];
435 [scvm defer
: anInvocation
];
437 [self setEditingInactive
:NO
]; // in this way we know that editing was started by a mouse click rather than a key down
439 bool constructionmode
= mTopView
->ConstructionMode();
440 if(!constructionmode
)
442 mSCViewObject
->mouseDownAction(scpoint
, modifiers
,theEvent
);
443 mSCViewObject
->mouseBeginTrack(scpoint
, modifiers
,theEvent
);
445 mSCViewObject
->setConstructionModeFromPoint(scpoint
);
447 [self displayIfNeeded
];
449 while (keepOn
&& !mDragStarted
) {
450 theEvent
= [[self window
] nextEventMatchingMask
: NSLeftMouseUpMask |NSRightMouseUp | NSOtherMouseUp |
451 NSLeftMouseDraggedMask | NSRightMouseDragged | NSOtherMouseDragged
452 | NSKeyDownMask | NSKeyUpMask
454 modifiers
= [theEvent modifierFlags
]; // added
455 mouseLoc
= [self convertPoint
:[theEvent locationInWindow
] fromView
:nil];
456 //isInside = [self mouse:mouseLoc inRect:[self bounds]];
457 scpoint
= SCMakePoint(mouseLoc.x
, mouseLoc.y
);
458 int evtype
= [theEvent type
];
459 switch ([theEvent type
]) {
460 case NSLeftMouseDown
:
461 case NSRightMouseDown
:
464 mSCViewObject
->doConstructionMove(scpoint
);
467 mSCViewObject
->mouseDownAction(scpoint
, modifiers
,theEvent
);
470 case NSLeftMouseDragged
:
471 case NSRightMouseDragged
:
472 case NSOtherMouseDragged
:
475 mSCViewObject
->doConstructionMove(scpoint
);
478 mSCViewObject
->mouseTrack(scpoint
, modifiers
,theEvent
);
479 mSCViewObject
->mouseMoveAction(scpoint
, modifiers
,theEvent
);
488 // view->doConstructionMove(scpoint);
492 if(mouseMoved
) { // check if this was just a mouse down or also a drag; if the latter end editing
493 [[self window
] endEditingFor
:self];
494 [self setEditingInactive
:YES
];
495 //[[self window] makeFirstResponder:[self superview]];
496 // trick focus ring into drawing
497 SEL sel
= @selector(setNeedsDisplay
:);
498 NSMethodSignature
*sig
= [NSView instanceMethodSignatureForSelector
: sel
];
499 NSInvocation
*anInvocation
= [NSInvocation invocationWithMethodSignature
: sig
];
500 SCVirtualMachine
* scvm
= [SCVirtualMachine sharedInstance
];
501 [anInvocation setTarget
: [self superview
]];
502 [anInvocation setSelector
: sel
];
504 [anInvocation setArgument
: &flag atIndex
: 2];
505 [scvm defer
: anInvocation
];
507 // if(!view.GetSCObj()) break;
508 mSCViewObject
->mouseUpAction(scpoint
, modifiers
,theEvent
);
509 mSCViewObject
->mouseEndTrack(scpoint
, modifiers
,theEvent
);
514 if(!constructionmode
)
516 [self keyDown
:theEvent
];
520 if(!constructionmode
)
522 [self keyUp
:theEvent
];
526 post("evtype %d %4.4s\n", evtype
, (char*)&evtype
);
527 /* Ignore any other kind of event. */
531 [self displayIfNeeded
];
539 -(void)mouseMoved
:(NSEvent
*)theEvent
542 unsigned int modifiers
= [theEvent modifierFlags
];
543 mouseLoc
= [self convertPoint
:[theEvent locationInWindow
] fromView
:nil];
544 SCPoint scpoint
= SCMakePoint(mouseLoc.x
, mouseLoc.y
);
547 // view->makeFocus(true);
548 mSCViewObject
->mouseOver(scpoint
, modifiers
, theEvent
);
552 const int circDiam
= 20;
554 - (NSImage
*) makeDragImage
: (PyrSlot
*)slot label
: (NSString
*)label
563 PyrClass
*classobj
= classOfSlot(slot
);
564 nsstring
= [NSString stringWithCString
: slotRawSymbol(&classobj
->name
)->name encoding
:[NSString defaultCStringEncoding
]];
565 if (!nsstring
) return 0;
567 nsstring
= @
"No Data!";
570 NSMutableDictionary
*dict
= [NSMutableDictionary dictionary
];
571 NSFont
*font
= [NSFont fontWithName
: @
"Helvetica" size
: 12];
573 [dict setObject
: font forKey
: NSFontAttributeName
];
575 NSSize strSize
= [nsstring sizeWithAttributes
: dict
];
576 NSRect strRect
= NSMakeRect(circDiam
, 0, circDiam
+ strSize.width
, strSize.height
);
578 NSSize size
= NSMakeSize(circDiam
+strSize.width
, sc_max(circDiam
, strSize.height
));
580 NSImage
*image
= [[NSImage alloc
] initWithSize
: size
];
581 if (!image
) return 0;
586 NSColor
*colorClear
= [NSColor colorWithCalibratedRed
: 0
590 NSColor
*colorTransBlack
= [NSColor colorWithCalibratedRed
: 0
594 NSColor
*colorTransBlue
= [NSColor colorWithCalibratedRed
: 0
598 /*NSColor *colorTransLtBlue = [NSColor colorWithCalibratedRed: 0.8
602 NSColor
*colorTransWhite
= [NSColor colorWithCalibratedRed
: 1
606 NSColor
*colorCaptionBackgnd
= [NSColor colorWithCalibratedRed
: 0
610 NSColor
*colorWhite
= [NSColor colorWithCalibratedRed
: 1
615 [dict setObject
: colorWhite forKey
: NSForegroundColorAttributeName
];
619 [NSBezierPath fillRect
: NSMakeRect(0,0,size.width
,size.height
)];
620 NSBezierPath
*path
= [NSBezierPath bezierPathWithOvalInRect
: NSMakeRect(1,1,circDiam
-2,circDiam
-2)];
622 [path setLineWidth
: 1.5];
623 [colorTransBlue set
];
626 NSBezierPath
*hilite
= [NSBezierPath bezierPathWithOvalInRect
:
627 NSMakeRect(circDiam
*0.3, circDiam
*0.7, circDiam
*0.4, circDiam
*0.15)];
629 [colorTransWhite set
];
632 [colorTransBlack set
];
635 [colorCaptionBackgnd set
];
636 [NSBezierPath fillRect
: strRect
];
638 [nsstring drawInRect
: strRect withAttributes
: dict
];
646 - (void) beginDragFrom
: (NSPoint
)where of
: (PyrSlot
*)slot string
:(NSString
*) string label
:(NSString
*) label
648 NSImage
*image
= [self makeDragImage
: slot label
: label
];
650 NSPasteboard
*pboard
= [NSPasteboard pasteboardWithName
: NSDragPboard
];
651 [pboard declareTypes
: [NSArray arrayWithObjects
: sSCObjType
, NSStringPboardType
, nil] owner
: self];
654 NSData
*data
= [NSData dataWithBytes
: &fakeData length
: sizeof(int)];
656 [pboard setData
: data forType
: sSCObjType
];
657 [pboard setString
: string forType
: NSStringPboardType
];
659 where.x
-= circDiam
/ 2;
660 where.y
+= circDiam
/ 4;
662 NSSize dragOffset
= NSMakeSize(0.0, 0.0);
664 [self dragImage
: image at
: where offset
: dragOffset event
: [NSApp currentEvent
]
665 pasteboard
: pboard source
: self slideBack
: YES
];
668 //- (void)mouseDragged:(NSEvent *)theEvent
670 // NSSize dragOffset = NSMakeSize(0.0, 0.0);
671 // NSPasteboard *pboard;
673 // pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
674 // [pboard declareTypes:[NSArray arrayWithObjects:sSCObjType, NSStringPboardType, nil] owner:self];
677 // NSData *data = [NSData dataWithBytes: &fakeData length: sizeof(int)];
679 // [pboard setData: data forType: sSCObjType];
680 // [pboard setString: [self stringValue] forType: NSStringPboardType];
682 // [self dragImage:[[[self window] fieldEditor:NO forObject:self] dragImageForSelectionWithEvent:NSMakePoint(0.0, 0.0)] at:[self imageLocation] offset:dragOffset
683 // event:theEvent pasteboard:pboard source:self slideBack:YES];
688 - (void)setSCView
: (class SCTextField
*)inObject
690 mSCViewObject
= inObject
;
693 -(BOOL) acceptsFirstResponder
695 return mAcceptsFirstResponder
;
698 -(void) setAcceptsFirstResponder
: (BOOL) flag
700 mAcceptsFirstResponder
= flag
;
704 // TEST: For tab-index
705 //- (BOOL)becomeFirstResponder
707 // if(!mSCViewObject->isFocus()){
708 // [self resignFirstResponder];
709 // [mSCViewObject->getTop()->focusView()->focusResponder() becomeFirstResponder];
711 // } else return [super becomeFirstResponder];
713 //-(BOOL) acceptsFirstResponder
718 //- (BOOL)resignFirstResponder
720 // post("resignFirstResponder\n");
721 // [[self window] endEditingFor:self];
725 // this for keyDowns. KeyUps come in keyUp below.
726 - (BOOL)textView
:(NSTextView
*)aTextView shouldChangeTextInRange
:(NSRange
)affectedCharRange replacementString
:(NSString
*)replacementString
729 NSEvent
* event
= [NSApp currentEvent
];
730 NSString
*characters
= [event characters
];
731 unsigned int modifiers
= [event modifierFlags
];
732 unichar character
= 0;
733 if([characters length
] > 0) {
734 character
= [characters characterAtIndex
: 0];
736 if ([event keyCode
] == 53){ //escape key breaks from modal or fullscreen windows
737 [[self window
] keyDown
:event
];
739 mSCViewObject
->keyDown(character
, modifiers
,[event keyCode
]);
743 // handle tabs and enter
744 - (BOOL)textView
:(NSTextView
*)aTextView doCommandBySelector
:(SEL)aSelector
747 //NSLog(@"sel: %@", NSStringFromSelector(aSelector));
748 if (aSelector
== @selector(insertTab
:)){
749 mSCViewObject
->tabPrevFocus();
751 } else if (aSelector
== @selector(insertBacktab
:)){
752 mSCViewObject
->tabNextFocus();
754 } else if (aSelector
== @selector(insertNewline
:)){
755 [[self window
] endEditingFor
:self];
757 pthread_mutex_lock (&gLangMutex
);
758 PyrSymbol
*method
= getsym("doAction");
760 if ((mObj
= mSCViewObject
->GetSCObj())) {
761 VMGlobals
*g
= gMainVMGlobals
;
763 ++g
->sp
; SetObject(g
->sp
, mObj
);
764 runInterpreter(g
, method
, 1);
765 g
->canCallOS
= false;
767 pthread_mutex_unlock (&gLangMutex
);
768 //NSLog(@"sv: %@", [self superview]);
769 [self setEditingInactive
:YES
];
770 [[self window
] makeFirstResponder
:[self superview
]];
771 //NSLog(@"firstresp: %@", [[self window] firstResponder]);
772 return NO
; // this will let the field editor end editing
773 } else if (aSelector
== @selector(moveUp
:) || aSelector
== @selector(moveDown
:)){ // stop editing and forward key event (for numbox)
774 NSEvent
* event
= [NSApp currentEvent
];
775 NSString
*characters
= [event characters
];
776 unsigned int modifiers
= [event modifierFlags
];
777 unichar character
= 0;
778 if([characters length
] > 0) {
779 character
= [characters characterAtIndex
: 0];
781 [[self window
] endEditingFor
:self];
782 [self setEditingInactive
:YES
];
783 [[self window
] makeFirstResponder
:[self superview
]];
784 mSCViewObject
->keyDown(character
, modifiers
,[event keyCode
]);
791 - (NSDragOperation
)draggingEntered
:(id < NSDraggingInfo
>)dragInfo
{
792 NSPasteboard
* pboard
= [dragInfo draggingPasteboard
];
793 if ([[pboard types
] containsObject
: sSCObjType
]) {
794 return mSCViewObject
->draggingEntered();
795 } else if ([[pboard types
] containsObject
: NSStringPboardType
]) {
796 NSString
*nsstring
= [pboard stringForType
: NSStringPboardType
];
797 if (!nsstring
) return NSDragOperationNone
;
799 pthread_mutex_lock (&gLangMutex
);
800 VMGlobals
*g
= gMainVMGlobals
;
801 PyrString
* pstrobj
= newPyrString(g
->gc
, [nsstring UTF8String
], 0, true);
802 int classVarIndex
= slotRawInt(&getsym("SCView")->u.classobj
->classVarIndex
);
803 SetObject(&g
->classvars
->slots
[classVarIndex
+0], pstrobj
);
804 g
->gc
->GCWrite(g
->classvars
, pstrobj
);
805 //PyrSymbol *method = getsym("importDrag");
806 //g->canCallOS = true;
807 ++g
->sp
; SetObject(g
->sp
, s_scview
->u.classobj
);
808 //runInterpreter(g, method, 1);
809 //g->canCallOS = false;
811 pthread_mutex_unlock (&gLangMutex
);
814 NSData
*data
= [NSData dataWithBytes
: &fakeData length
: sizeof(int)];
815 [pboard setData
: data forType
: sSCObjType
];
817 } else if ([[pboard types
] containsObject
: NSFilenamesPboardType
]) {
818 NSArray
*files
= [pboard propertyListForType
: NSFilenamesPboardType
];
819 if (!files
) return NSDragOperationNone
;
820 pthread_mutex_lock (&gLangMutex
);
821 VMGlobals
*g
= gMainVMGlobals
;
822 int size
= [files count
];
823 PyrObject
* array
= newPyrArray(g
->gc
, size
, 0, true);
825 for (int i
=0; i
<size
; ++i
) {
826 NSString
*path
= [files objectAtIndex
: i
];
827 PyrString
*string
= newPyrString(g
->gc
, [path UTF8String
], 0, true);
828 SetObject(array
->slots
+ array
->size
, string
);
830 g
->gc
->GCWrite(array
, string
);
833 int classVarIndex
= slotRawInt(&getsym("SCView")->u.classobj
->classVarIndex
);
834 SetObject(&g
->classvars
->slots
[classVarIndex
+0], array
);
835 g
->gc
->GCWrite(g
->classvars
, array
);
837 pthread_mutex_unlock (&gLangMutex
);
840 NSData
*data
= [NSData dataWithBytes
: &fakeData length
: sizeof(int)];
841 [pboard setData
: data forType
: sSCObjType
];
844 return NSDragOperationNone
;
849 - (BOOL)performDragOperation
:(id <NSDraggingInfo
>)sender
{
851 return mSCViewObject
->performDrag();
854 - (void)keyUp
:(NSEvent
*)event
857 //post("doKeyUpAction\n");
858 NSString
*characters
= [event characters
];
859 unsigned int modifiers
= [event modifierFlags
];
860 unichar character
= 0;
861 if([characters length
] > 0) {
862 character
= [characters characterAtIndex
: 0];
864 mSCViewObject
->keyUp(character
, modifiers
,[event keyCode
]);
868 void QDDrawBevelRect(CGContextRef cgc
, CGRect bounds
, float width
, bool inout);
869 - (void)drawRect
:(NSRect
)aRect
871 [super drawRect
:aRect
];
873 CGContextRef cgc
= (CGContextRef
)[[NSGraphicsContext currentContext
] graphicsPort
];
874 CGContextSaveGState(cgc
);
875 #if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4)
876 QDDrawBevelRect(cgc
, (*(CGRect
*)&([self bounds
])), 1, true);
878 QDDrawBevelRect(cgc
, NSRectToCGRect([self bounds
]), 1, true);
880 CGContextRestoreGState(cgc
);
884 // doing this here keeps C++ classes much simpler
885 - (void) addNumberFormatter
887 [NSNumberFormatter setDefaultFormatterBehavior
:NSNumberFormatterBehavior10_4
];
888 mFormatter
= [[[NSNumberFormatter alloc
] init
] autorelease
];
889 [mFormatter setNumberStyle
: NSNumberFormatterDecimalStyle
];
890 [mFormatter setAlwaysShowsDecimalSeparator
:NO
];
891 [mFormatter setExponentSymbol
:@
"e"];
892 [mFormatter setMaximumFractionDigits
:20];
893 [mFormatter setDecimalSeparator
:@
"."];
894 [mFormatter setUsesGroupingSeparator
:NO
];
895 [[self cell
] setFormatter
:mFormatter
];
898 // with these two methods we can check in C++ keyDown methods to see if editing is active
899 // if not, we start it and replace the string in the field editor
900 - (void) setEditingInactive
: (BOOL)flag
902 mEditingInactive
= flag
;
905 - (BOOL) editingInactive
907 return mEditingInactive
;
911 @implementation SCNSMenuItem
913 - (void)setSCObject
: (struct PyrObject
*)inObject
915 mMenuItemObj
= inObject
;
918 - (struct PyrObject
*)getSCObject
923 - (void)doAction
: (id)sender
925 // post("doAction \n");
926 pthread_mutex_lock (&gLangMutex
);
927 PyrObject
* pobj
= [self getSCObject
];
928 if(compiledOK
&& pobj
){
929 PyrSymbol
*method
= getsym("doAction");
930 VMGlobals
*g
= gMainVMGlobals
;
932 ++g
->sp
; SetObject(g
->sp
, pobj
);
933 ++g
->sp
; SetInt(g
->sp
, 1);
934 runInterpreter(g
, method
, 2);
935 g
->canCallOS
= false;
937 pthread_mutex_unlock (&gLangMutex
);
942 @implementation SCNSLevelIndicator
944 - (void)drawRect
:(NSRect
)aRect
946 if(drawPeak
) { // make warning and critical show for peak not value if peak is drawn
947 if(criticalAboveWarning
) {
948 if(peakValue
>= critical
) {
949 [self setCriticalValue
: value
];
950 [self setWarningValue
: value
- 0.1];
951 } else if (peakValue
>= warning
) {
952 [self setWarningValue
: value
];
953 [self setCriticalValue
: value
+ 0.1];
955 [self setWarningValue
: 1.1];
956 [self setCriticalValue
: 1.1];
959 if(peakValue
<= critical
) {
960 [self setCriticalValue
: value
];
961 [self setWarningValue
: value
+ 0.1];
962 } else if (peakValue
<= warning
) {
963 [self setWarningValue
: value
];
964 [self setCriticalValue
: value
- 0.1];
966 [self setWarningValue
: -0.1];
967 [self setCriticalValue
: -0.1];
971 [super drawRect
:aRect
];
973 CGContextRef cgc
= (CGContextRef
)[[NSGraphicsContext currentContext
] graphicsPort
];
974 CGContextSaveGState(cgc
);
975 CGContextSetRGBFillColor(cgc
, 1.0, 1.0, 0.0, 0.6);
977 //peakRect = CGRectMake(peakLevel, aRect.origin.y + peakSubtract, 3.f, aRect.size.height - peakSubtract);
978 peakRect
= CGRectMake(peakLevel
, peakY
, 3.f
, peakHeight
);
979 CGContextFillRect(cgc
, peakRect
);
980 CGContextRestoreGState(cgc
);
982 [super drawRect
:aRect
];
986 - (id)initWithFrame
:(NSRect
)frameRect
988 if (![super initWithFrame
:frameRect
])
994 value
= peakValue
= 0.0;
995 critical
= warning
= 1.1;
996 criticalAboveWarning
= YES
;
997 [self prepPeakBounds
];
1001 - (void)setFrame
:(NSRect
)frameRect
1003 [super setFrame
:frameRect
];
1004 [self prepPeakBounds
];
1005 [self setNeedsDisplay
:YES
];
1008 - (void)setDrawPeak
:(BOOL)flag
1012 [self setWarningValue
: warning
];
1013 [self setCriticalValue
: critical
];
1015 [self prepPeakBounds
];
1016 [self setNeedsDisplay
:YES
];
1019 - (void)setDoubleValue
:(double)val
1021 [super setDoubleValue
:val
];
1025 - (void)setMaxValue
:(double)maxVal
1027 peakValue
= (peakValue
/ [self maxValue
]) * maxVal
;
1028 [super setMaxValue
:maxVal
];
1031 - (void)setIsVertical
:(BOOL)flag
1034 [self prepPeakBounds
];
1035 [self setNeedsDisplay
:YES
];
1038 - (void)setPeakSubtract
:(float)val
1041 [self prepPeakBounds
];
1042 [self setNeedsDisplay
:YES
];
1045 - (void)setPeakLevel
:(float)val
1047 peakValue
= val
* [self maxValue
];
1048 peakLevel
= val
* ([self bounds
].size.width
- 3);
1049 //NSLog(@"peakLevel %f", peakLevel);
1050 [self setNeedsDisplay
:YES
];
1053 - (void)prepPeakBounds
1055 NSRect bounds
= [self bounds
];
1056 peakY
= bounds.origin.y
+ peakSubtract
;
1057 peakHeight
= bounds.size.height
- peakSubtract
;
1060 - (void)setUpWarning
:(double)val
1062 warning
= nextafter(val
, val
+ 1.0);
1063 if(critical
> warning
) {
1064 criticalAboveWarning
= YES
;
1066 criticalAboveWarning
= NO
;
1068 [self setWarningValue
:warning
];
1071 - (void)setUpCritical
:(double)val
1073 critical
= nextafter(val
, val
+ 1.0);
1074 if(critical
> warning
) {
1075 criticalAboveWarning
= YES
;
1077 criticalAboveWarning
= NO
;
1079 [self setCriticalValue
:critical
];
1084 @implementation SCNSFlippedView
1086 - (BOOL)isFlipped
{ return YES
; }
1091 @implementation SCNSWebView
1096 enterExecutesSelection
= YES
;
1099 - (void)setSCObject
: (class SCWebView
*)inObject
1101 mSCWebView
= inObject
;
1104 - (class SCWebView
*)getSCObject
1109 - (void)setHandleLinks
: (bool)handle
1111 handleLinks
= handle
;
1114 - (void)resetLoadCount
1119 - (BOOL)shouldCloseWithWindow
{
1121 [[SCVirtualMachine sharedInstance
] removeDeferredOperationsFor
:self];
1126 - (void)webView
:(WebView
*)sender didFinishLoadForFrame
:(WebFrame
*)frame
1128 loadCount
= loadCount
- 1;
1129 if (loadCount
<= 0 && mSCWebView
) {
1131 SEL selector
= @selector(doLoadAction
);
1132 NSInvocation
*invocation
= [NSInvocation invocationWithMethodSignature
:
1133 [sender methodSignatureForSelector
: selector
]];
1134 [invocation setTarget
:sender
];
1135 [invocation setSelector
: selector
];
1137 [[SCVirtualMachine sharedInstance
] defer
: invocation
];
1141 - (void)webView
:(WebView
*)sender didStartProvisionalLoadForFrame
:(WebFrame
*)frame
1143 loadCount
= loadCount
+ 1;
1146 - (void)webView
:(WebView
*)sender didFailProvisionalLoadWithError
:(NSError
*)error forFrame
:(WebFrame
*)frame
1148 NSLog(@
"didFailProvisionalLoadWithError: %@",[error localizedDescription
]);
1149 if ([error code
] == NSURLErrorCancelled
) return; // this is Error -999
1151 post("SCWebView load request failed: '%s'\n", [[error localizedDescription
] cStringUsingEncoding
:[NSString defaultCStringEncoding
]]);
1152 SEL selector
= @selector(doFailAction
);
1153 NSInvocation
*invocation
= [NSInvocation invocationWithMethodSignature
:
1154 [sender methodSignatureForSelector
: selector
]];
1155 [invocation setTarget
:sender
];
1156 [invocation setSelector
: selector
];
1158 [[SCVirtualMachine sharedInstance
] defer
: invocation
];
1162 - (void)doFailAction
1165 mSCWebView
->doLoadFailedAction();
1169 - (void)doLoadAction
1172 mSCWebView
->doOnLoadAction();
1176 - (void)webView
:(WebView
*)sender didFailLoadWithError
:(NSError
*)error
1178 NSLog(@
"didFailLoadWithError: %@",[error localizedDescription
]);
1179 if ([error code
] == NSURLErrorCancelled
) return; // this is Error -999
1181 post("SCWebView load request failed: '%s'\n", [[error localizedDescription
] cStringUsingEncoding
:[NSString defaultCStringEncoding
]]);
1182 SEL selector
= @selector(doFailAction
);
1183 NSInvocation
*invocation
= [NSInvocation invocationWithMethodSignature
:
1184 [sender methodSignatureForSelector
: selector
]];
1185 [invocation setTarget
:sender
];
1186 [invocation setSelector
: selector
];
1188 [[SCVirtualMachine sharedInstance
] defer
: invocation
];
1192 // call link action if set, otherwise proceed
1193 - (void)webView
:(WebView
*)webView decidePolicyForNavigationAction
:(NSDictionary
*)actionInformation request
:(NSURLRequest
*)request frame
:(WebFrame
*)frame decisionListener
:(id )listener
1195 //NSLog(@"decide policy");
1196 int actionKey
= [[actionInformation objectForKey
:WebActionNavigationTypeKey
] intValue
];
1197 if(actionKey
== WebNavigationTypeLinkClicked
) {
1198 //NSLog(@"link clicked");
1201 //NSLog(@"handle link");
1204 //NSLog(@"fire action");
1206 NSString
*urlString
= [[[request URL
] absoluteString
] retain
];
1208 SEL selector
= @selector(doLinkAction
:);
1209 NSInvocation
*invocation
= [NSInvocation invocationWithMethodSignature
:
1210 [webView methodSignatureForSelector
: selector
]];
1211 [invocation setTarget
:webView
];
1212 [invocation setSelector
: selector
];
1213 [invocation setArgument
:&urlString atIndex
:2];
1215 [[SCVirtualMachine sharedInstance
] defer
: invocation
];
1219 //NSLog(@"link not clicked");
1225 - (void)webView
:(WebView
*)webView unableToImplementPolicyWithError
:(NSError
*)error frame
:(WebFrame
*)frame
1227 NSLog(@
"unableToImplementPolicyWithError: %@",[error localizedDescription
]);
1230 - (void)doLinkAction
:(NSString
*)urlString
1232 VMGlobals
*g
= gMainVMGlobals
;
1233 const char * cstr
= [urlString UTF8String
];
1234 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
1235 mSCWebView
->doLinkClickedAction(string
);
1236 [urlString release
];
1239 - (BOOL)webView
:(WebView
*)webView shouldInsertText
:(NSString
*)insertText replacingDOMRange
:(DOMRange
*)range givenAction
:(WebViewInsertAction
)action
1242 NSEvent
* event
= [NSApp currentEvent
];
1243 NSString
*characters
= [event characters
];
1244 unsigned int modifiers
= [event modifierFlags
];
1245 unichar character
= 0;
1246 if([characters length
] > 0) {
1247 character
= [characters characterAtIndex
: 0];
1249 if ([event keyCode
] == 53){ //escape key breaks from modal or fullscreen windows
1250 [[self window
] keyDown
:event
];
1252 mSCWebView
->keyDown(character
, modifiers
,[event keyCode
]);
1253 if ([characters isEqual
: @
"\03"] ||
1254 (([characters isEqual
: @
"\n"] ||
[characters isEqual
: @
"\r"]) && ([event modifierFlags
] & (NSControlKeyMask | NSShiftKeyMask
)))) {
1255 [self executeSelection
: self];
1262 - (void)keyDown
:(NSEvent
*)event
1264 NSString
*characters
= [event characters
];
1265 unsigned int modifiers
= [event modifierFlags
];
1266 unichar character
= 0;
1267 if([characters length
] > 0) {
1268 character
= [characters characterAtIndex
: 0];
1270 if ([event keyCode
] == 53){ //escape key breaks from modal or fullscreen windows
1271 [[self window
] keyDown
:event
];
1273 mSCWebView
->keyDown(character
, modifiers
,[event keyCode
]);
1274 if ([characters isEqual
: @
"\03"] ||
1275 (([characters isEqual
: @
"\n"] ||
[characters isEqual
: @
"\r"]) && ([event modifierFlags
] & (NSControlKeyMask | NSShiftKeyMask
)))) {
1276 [self executeSelection
: self];
1278 [super keyDown
:event
];
1283 - (void) setEnterExecutesSelection
: (BOOL) flag
1285 enterExecutesSelection
= flag
;
1288 - (void)sendSelection
: (NSString
*) nsmethodName
1290 const char * methodName
= [nsmethodName UTF8String
];
1295 [self setSelection
];
1297 pthread_mutex_lock(&gLangMutex
);
1298 runLibrary(getsym(methodName
));
1299 pthread_mutex_unlock(&gLangMutex
);
1303 - (void)setSelection
;
1305 NSString
* selection
= [self stringByEvaluatingJavaScriptFromString
:@
"(function (){selectLine(); selObj = window.getSelection(); string = selObj.toString(); selObj.collapseToEnd(); return string })();"];
1306 const char *text
= [selection UTF8String
];
1307 int textlength
= strlen(text
);
1309 [[SCVirtualMachine sharedInstance
] setCmdLine
: text length
: textlength
];
1312 - (IBAction
)openCode
:(id)sender
1314 [self sendSelection
: @
"openCodeFile"];
1317 - (IBAction
) showHelpFor
: (id) sender
1319 [self sendSelection
: @
"showHelp"];
1322 - (IBAction
)showHelpSearch
:(id)sender
{
1323 [self sendSelection
: @
"showHelpSearch"];
1326 - (IBAction
)methodTemplates
: (id)sender
1328 [self sendSelection
: @
"methodTemplates"];
1331 - (IBAction
)methodReferences
: (id)sender
1333 [self sendSelection
: @
"methodReferences"];
1336 - (IBAction
)executeSelection
: (id) sender
1338 if(enterExecutesSelection
)
1339 [self sendSelection
: @
"interpretPrintCmdLine" ];
1342 // workaround for plaintext copy
1343 - (BOOL)webView
:(WebView
*)webView doCommandBySelector
:(SEL)command
1345 if (command
== @selector(copy
:)) {
1346 NSString
*markup
= [[self selectedDOMRange
] markupString
];
1347 NSData
*data
= [markup dataUsingEncoding
: NSUTF8StringEncoding
];
1348 NSNumber
*n
= [NSNumber numberWithUnsignedInteger
: NSUTF8StringEncoding
];
1349 NSDictionary
*options
= [NSDictionary dictionaryWithObject
:n forKey
: NSCharacterEncodingDocumentOption
];
1350 NSAttributedString
*as
= [[NSAttributedString alloc
] initWithHTML
:data options
:options documentAttributes
: NULL
];
1351 NSString
*selectedString
= [as string
];
1354 NSPasteboard
*pasteboard
= [NSPasteboard generalPasteboard
];
1355 [pasteboard clearContents
];
1356 NSArray
*objectsToCopy
= [NSArray arrayWithObject
: selectedString
];
1357 [pasteboard writeObjects
:objectsToCopy
];
1363 - (void)cmdF
:(id)sender
{
1364 [self keyDown
:[NSApp currentEvent
]];
1368 NSRect
SCtoNSRect(SCRect screct
);
1370 SCView
* NewSCCocoaTextView(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
1372 return new SCCocoaTextView(inParent
, inObj
, inBounds
);
1375 SCCocoaTextView
::SCCocoaTextView(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
1376 : SCView(inParent
, inObj
, inBounds
)
1379 mLoadLinkInView
= true;
1381 NSRect matrect
= SCtoNSRect(getDrawBounds());
1382 mTextView
= [[SCTextView alloc
] initWithFrame
:matrect
];
1383 NSView
*view
= mTop
->GetNSView();
1384 mCocoaToLangAction
= [SCCocoaTextViewResponder alloc
];
1385 [mCocoaToLangAction setSCView
: this];
1386 [mTextView setAutoresizingMask
: 63];
1387 [[mTextView textContainer
] setWidthTracksTextView
: YES
];
1388 [mTextView setAllowsUndo
: YES
];
1389 [mTextView setRichText
: YES
];
1390 [mTextView setSmartInsertDeleteEnabled
: NO
];
1391 [mTextView setImportsGraphics
: YES
];
1392 [mTextView setFont
: [NSFont fontWithName
: @
"Monaco" size
: 9]];
1393 [mTextView setSelectedRange
: NSMakeRange(0,0)];
1394 [mTextView setLangClassToCall
:@
"SCView"
1395 withKeyDownActionIndex
:1 withKeyUpActionIndex
:2];
1396 [mTextView setObjectKeyDownActionIndex
:4 setObjectKeyUpActionIndex
:5];
1397 mScrollView
= [[NSScrollView alloc
] initWithFrame
: matrect
];
1398 [mScrollView setDocumentView
: mTextView
];
1399 [mTextView setDelegate
: mCocoaToLangAction
];
1400 [view addSubview
: mScrollView
];
1401 [[mTextView textContainer
] setContainerSize
:NSMakeSize([mScrollView contentSize
].width
, FLT_MAX
)];
1402 //This is a hack, otherwise the mTextView always has focus even if makeFirstResponder: view is called...
1403 [mTextView setAcceptsFirstResponder
:NO
];
1404 [mScrollView setDrawsBackground
:YES
];
1405 [mCocoaToLangAction setUsesTabToFocusNextView
:YES
];
1406 [mCocoaToLangAction setEnterExecutesSelection
:YES
];
1407 // [mTextView autorelease];
1408 // [mScrollView autorelease];
1410 setVisibleFromParent();
1413 SCCocoaTextView
::~
SCCocoaTextView()
1415 [mScrollView removeFromSuperview
];
1416 [mCocoaToLangAction release
];
1417 [mTextView release
];
1418 [mScrollView release
];
1422 void SCCocoaTextView
::tabPrevFocus()
1424 mTop
->tabPrevFocus();
1426 void SCCocoaTextView
::tabNextFocus()
1428 //post("next focus\n");
1429 mTop
->tabNextFocus();
1431 void SCCocoaTextView
::makeFocus(bool focus
)
1434 if (canFocus() && !isFocus()) {
1435 [mTextView setAcceptsFirstResponder
:YES
];
1436 //[[mTextView window] makeFirstResponder: mTextView];
1440 [mTextView setAcceptsFirstResponder
:NO
];
1443 SCView
::makeFocus(focus
);
1447 int slotGetSCRect(PyrSlot
* a
, SCRect
*r
);
1448 extern PyrSymbol
*s_font
;
1449 int slotBackgroundVal(PyrSlot
*slot
, DrawBackground
**ioPtr
);
1451 void SCCocoaTextView
::setBounds(SCRect inBounds
)
1454 [[mScrollView superview
] setNeedsDisplayInRect
:[mScrollView frame
]];
1455 if(!(mParent
->isSubViewScroller())){
1456 SCRect pbounds
= mParent
->getLayout().bounds
;
1457 mLayout.bounds.x
= mBounds.x
+ pbounds.x
;
1458 mLayout.bounds.y
= mBounds.y
+ pbounds.y
;
1459 mLayout.bounds.width
= mBounds.width
;
1460 mLayout.bounds.height
= mBounds.height
;
1462 mLayout.bounds
= mBounds
;
1464 [mScrollView setFrame
: SCtoNSRect(mLayout.bounds
)];
1465 //[mTextView setFrame: SCtoNSRect(mLayout.bounds)]; // not needed - br
1467 // [mScrollView setBounds: SCtoNSRect(mBounds)];
1468 // [mTextView setBounds: SCtoNSRect(mBounds)];
1469 // [mScrollView setNeedsDisplay: YES]; // not needed - br
1470 // [mTextView setNeedsDisplay: YES]; // not needed - br
1473 void SCCocoaTextView
::keyDown(int character
, int modifiers
, unsigned short keycode
)
1477 void SCCocoaTextView
::keyUp(int character
, int modifiers
, unsigned short keycode
)
1482 int slotColorVal(PyrSlot
*slot
, SCColor
*sccolor
);
1483 int setSlotColor(PyrSlot
*slot
, SCColor
*sccolor
);
1485 int SCCocoaTextView
::setProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
1488 char *name
= symbol
->name
;
1490 if (strcmp(name
, "visible")==0) {
1491 bool visible
= IsTrue(slot
);
1493 setVisibleFromParent();
1497 if (strcmp(name
, "usesTabToFocusNextView")==0) {
1498 if(IsTrue(slot
))[mCocoaToLangAction setUsesTabToFocusNextView
:YES
];
1499 else [mCocoaToLangAction setUsesTabToFocusNextView
:NO
];
1502 if (strcmp(name
, "enterExecutesSelection")==0) {
1503 if(IsTrue(slot
))[mCocoaToLangAction setEnterExecutesSelection
:YES
];
1504 else [mCocoaToLangAction setEnterExecutesSelection
:NO
];
1507 if (strcmp(name
, "setScrollersSize")==0) {
1508 if(IsTrue(slot
)) [[mScrollView verticalScroller
] setControlSize
: NSMiniControlSize
];
1509 else [mScrollView setAutohidesScrollers
:NO
];
1510 [mScrollView setNeedsDisplay
: YES
];
1515 if (strcmp(name
, "setAutohidesScrollers")==0) {
1516 if(IsTrue(slot
)) [mScrollView setAutohidesScrollers
:YES
];
1517 else [mScrollView setAutohidesScrollers
:NO
];
1518 [mScrollView setNeedsDisplay
: YES
];
1523 if (strcmp(name
, "setHasHorizontalScroller")==0) {
1524 if(IsTrue(slot
)) [mScrollView setHasHorizontalScroller
:YES
];
1525 else [mScrollView setHasHorizontalScroller
:NO
];
1526 [mScrollView setNeedsDisplay
: YES
];
1531 if (strcmp(name
, "setHasVerticalScroller")==0) {
1532 if(IsTrue(slot
)) [mScrollView setHasVerticalScroller
:YES
];
1533 else [mScrollView setHasVerticalScroller
:NO
];
1534 [mScrollView setNeedsDisplay
: YES
];
1537 if (strcmp(name
, "setEditable")==0) {
1538 if(IsTrue(slot
)) [mTextView setEditable
:YES
];
1539 else [mTextView setEditable
:NO
];
1542 if (strcmp(name
, "bounds")==0) {
1544 //add avariable to choos if this should resize the textview too
1545 err
= slotGetSCRect(slot
, &screct
);
1546 if (err
) return err
;
1553 if (strcmp(name
, "textBounds")==0) {
1555 err
= slotGetSCRect(slot
, &screct
);
1556 if (err
) return err
;
1557 [[mScrollView superview
] setNeedsDisplayInRect
:[mScrollView frame
]];
1560 [mTextView setFrame
: SCtoNSRect(screct
)];
1562 // [mScrollView setBounds: SCtoNSRect(mBounds)];
1563 // [mTextView setBounds: SCtoNSRect(mBounds)];
1564 [mScrollView setNeedsDisplay
: YES
];
1565 [mTextView setNeedsDisplay
: YES
];
1569 if (strcmp(name
, "selectedString")==0) {
1570 if(!isKindOfSlot(slot
, class_string
)) return errWrongType
;
1571 PyrString
* pstring
= slotRawString(slot
);
1572 if(!pstring
) return errNone
;
1573 NSRange selectedRange
= [mTextView selectedRange
];
1574 NSString
*string
= [NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
]];
1575 string
= [string substringToIndex
: pstring
->size
];
1576 if ([mTextView shouldChangeTextInRange
: selectedRange replacementString
: string
]) {
1577 [mTextView replaceCharactersInRange
: selectedRange withString
: string
];
1578 [mTextView didChangeText
];
1583 if (strcmp(name
, "open")==0) {
1584 if(!isKindOfSlot(slot
, class_string
)) return errWrongType
;
1585 PyrString
* pstring
= slotRawString(slot
);
1586 if(!pstring
) return errNone
;
1587 NSString
*path
= [NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
]];
1588 path
= [path substringToIndex
: pstring
->size
];
1589 int result
= open(path
);
1594 if (strcmp(name
, "background")==0) {
1595 err
= slotBackgroundVal(slot
, &mBackground
);
1596 if (err
) return err
;
1598 err
= slotColorVal(slot
, &rgb
);
1599 if (err
) return err
;
1600 NSColor
*color
= [NSColor colorWithCalibratedRed
: rgb.red
1604 [mTextView setBackgroundColor
: color
];
1605 [mScrollView setBackgroundColor
: color
];
1609 if (strcmp(name
, "setTextColor")==0) {
1610 if(!isKindOfSlot(slot
, class_array
)) return errWrongType
;
1611 PyrSlot
*slots
= slotRawObject(slot
)->slots
;
1613 int rangeStart
, rangeSize
;
1614 err
= slotColorVal(slots
+0, &rgb
);
1615 if (err
) return err
;
1616 err
= slotIntVal(slots
+1, &rangeStart
);
1617 if (err
) return err
;
1618 err
= slotIntVal(slots
+2, &rangeSize
);
1619 if (err
) return err
;
1622 NSColor
*color
= [NSColor colorWithCalibratedRed
: rgb.red
1627 //[[doc textView] setBackgroundColor: color];
1630 [mTextView setTextColor
: color
];
1631 [mTextView didChangeText
];
1634 int length
= [[mTextView string
] length
];
1635 if(rangeStart
>= length
) rangeStart
= length
- 1 ;
1636 if(rangeStart
+ rangeSize
>= length
) rangeSize
= length
- rangeStart
;
1637 NSRange selectedRange
= NSMakeRange(rangeStart
, rangeSize
);
1640 [mTextView setTextColor
: color range
: selectedRange
];
1641 [mTextView didChangeText
];
1645 if (strcmp(name
, "setFont")==0) {
1646 if(!isKindOfSlot(slot
, class_array
)) return errWrongType
;
1647 PyrSlot
*slots
=slotRawObject(slot
)->slots
;
1648 PyrSlot
*fontSlot
= slots
+0;
1649 if (IsNil(fontSlot
)) return errNone
; // use default font
1650 if (!(isKindOfSlot(fontSlot
, s_font
->u.classobj
))) return errWrongType
;
1651 PyrSlot
*nameSlot
= slotRawObject(fontSlot
)->slots
+0;
1652 PyrSlot
*sizeSlot
= slotRawObject(fontSlot
)->slots
+1;
1654 int err
= slotFloatVal(sizeSlot
, &size
);
1655 if (err
) return err
;
1657 PyrString
*pstring
= slotRawString(nameSlot
);
1658 NSString
*fontName
= [NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
]];
1659 fontName
= [fontName substringToIndex
: pstring
->size
];
1660 if (!fontName
) return errFailed
;
1661 NSFont
*font
= [NSFont fontWithName
: fontName size
: size
];
1662 if (!font
) return errFailed
;
1664 int rangeStart
, rangeSize
;
1665 err
= slotIntVal(slots
+1, &rangeStart
); //if -1 do not use range
1666 if (err
) return err
;
1667 err
= slotIntVal(slots
+2, &rangeSize
);
1668 if (err
) return err
;
1671 [mTextView setFont
: font
];
1674 NSString
* string
= [mTextView string
];
1675 int length
= [string length
];
1676 if(length
< 1) return errFailed
;
1677 if(rangeStart
>= length
) rangeStart
= length
- 1 ;
1678 if(rangeStart
+ rangeSize
>= length
) rangeSize
= length
- rangeStart
;
1679 NSRange selectedRange
= NSMakeRange(rangeStart
, rangeSize
);
1681 [mTextView setFont
: font range
: selectedRange
];
1685 // if (strcmp(name, "insertString")==0) {
1686 // if (!(isKindOfSlot(slot, class_string))) return errWrongType;
1687 // PyrString* string = slotRawString(slot);
1688 //// [doc insertText: string->s length: string->size];
1691 if (strcmp(name
, "insertStringInRange")==0) {
1692 if(!isKindOfSlot(slot
, class_array
)) return errWrongType
;
1693 PyrSlot
*slots
=slotRawObject(slot
)->slots
;
1694 PyrSlot
*stringSlot
= slots
+0;
1695 if (!(isKindOfSlot(stringSlot
, class_string
))) return errWrongType
;
1697 int rangeStart
, rangeSize
;
1698 int err
= slotIntVal(slots
+1, &rangeStart
); //if -1 do not use range
1699 if (err
) return err
;
1700 err
= slotIntVal(slots
+2, &rangeSize
);
1701 if (err
) return err
;
1703 PyrString
* pstring
= slotRawString(stringSlot
);
1704 NSRange selectedRange
;
1705 int length
= [[mTextView string
] length
];
1707 if(rangeSize
< 0) rangeSize
= length
- 1;
1708 if(rangeStart
>= length
) rangeStart
= length
- 1 ;
1709 if(rangeStart
+ rangeSize
>= length
) rangeSize
= length
- rangeStart
;
1711 if(rangeStart
<0) selectedRange
= NSMakeRange(0, length
);
1712 else selectedRange
= NSMakeRange(rangeStart
, rangeSize
);
1714 NSString
*string
= [NSString stringWithCString
:pstring
->s encoding
:[NSString defaultCStringEncoding
]];
1715 string
= [string substringToIndex
:pstring
->size
];
1716 BOOL editable
= [mTextView isEditable
];
1717 if(!editable
) [mTextView setEditable
:YES
]; //always allow programmatic editing
1719 if ([mTextView shouldChangeTextInRange
: selectedRange replacementString
: string
]) {
1720 [mTextView replaceCharactersInRange
: selectedRange withString
: string
];
1721 [mTextView didChangeText
];
1724 if(!editable
) [mTextView setEditable
:NO
];
1729 if (strcmp(name
, "setSyntaxColors")==0) {
1730 SyntaxColorize(mTextView
);
1734 if (strcmp(name
, "setUsesAutoInOutdent")==0) {
1735 bool uses
= IsTrue(slot
);
1736 [mTextView setUsesAutoInOutdent
: uses
];
1740 return SCView
::setProperty(symbol
, slot
);
1743 int SCCocoaTextView
::getProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
1745 char *name
= symbol
->name
;
1746 VMGlobals
*g
= gMainVMGlobals
;
1748 if (strcmp(name
, "string")==0) {
1749 NSString
* str
= [mTextView string
];
1750 const char * cstr
= [str UTF8String
];
1751 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
1752 SetObject(slot
, string
);
1756 if (strcmp(name
, "selectedString")==0) {
1757 NSString
* str
= [mTextView currentlySelectedTextOrLine
:NULL
];
1758 const char * cstr
= [str UTF8String
];
1759 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
1760 SetObject(slot
, string
);
1764 if (strcmp(name
, "selectedRange")==0) {
1765 NSRange range
= [mTextView selectedRange
];
1766 SetInt(slot
, range.length
);
1770 if (strcmp(name
, "selectedRangeLocation")==0) {
1771 NSRange range
= [mTextView selectedRange
];
1772 SetInt(slot
, range.location
);
1776 if (strcmp(name
, "path")==0) {
1778 const char * cstr
= [[mLastURL path
] UTF8String
];
1779 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
1780 SetObject(slot
, string
);
1781 } else SetNil(slot
);
1785 return SCView
::getProperty(symbol
, slot
);
1788 int SCCocoaTextView
::open(NSString
*path
)
1790 NSURL
*url
= [[NSURL alloc
] initWithString
: path
];
1791 if(!url
) return errFailed
;
1793 NSTextStorage
* text
= [mTextView textStorage
];
1795 NSString
* extension
= [path pathExtension
];
1797 if ([extension isEqualToString
: @
"html"] ||
[extension isEqualToString
: @
"htm"]) {
1799 SEL sel
= @selector(loadHTMLToTextView
:);
1800 NSMethodSignature
*sig
= [SCCocoaTextViewResponder instanceMethodSignatureForSelector
: sel
];
1801 SCVirtualMachine
* scvm
= [SCVirtualMachine sharedInstance
];
1803 NSInvocation
*anInvocation
= [NSInvocation invocationWithMethodSignature
: sig
];
1804 [anInvocation setTarget
: mCocoaToLangAction
];
1805 [anInvocation setSelector
: sel
];
1806 [anInvocation setArgument
:&url atIndex
:2];
1807 [scvm defer
: anInvocation
];
1811 [text beginEditing
]; // Bracket with begin/end editing for efficiency
1812 [[text mutableString
] setString
:@
""]; // Empty the document
1815 BOOL success
= [text readFromURL
:url options
:nil documentAttributes
:nil error
:&error
];
1817 NSLog(@
"Error opening file: %@", error
);
1824 if ([extension isEqualToString
: @
"sc"] ||
[extension isEqualToString
: @
"scd"]) {
1825 [mTextView setFont
: [NSFont fontWithName
: @
"Monaco" size
: 9]];
1826 SyntaxColorize(mTextView
);
1828 [mTextView scrollPoint
:NSMakePoint(0, 0)];
1835 void SCCocoaTextView
::setVisibleFromParent()
1837 if(mVisible
&& mParent
->isVisible()) {
1838 [mScrollView setHidden
:NO
];
1839 [mTextView setHidden
:NO
];
1842 [mScrollView setHidden
:YES
];
1843 [mTextView setHidden
:YES
];
1848 extern int ivxSCTextView_linkAction
;
1850 bool SCCocoaTextView
::linkAction(NSString
*url
)
1852 if(NotNil(mObj
->slots
+ ivxSCTextView_linkAction
)){
1853 pthread_mutex_lock (&gLangMutex
);
1854 PyrSymbol
*method
= getsym("doLinkAction");
1856 VMGlobals
*g
= gMainVMGlobals
;
1857 g
->canCallOS
= true;
1858 const char * cstr
= [url UTF8String
];
1859 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
1860 ++g
->sp
; SetObject(g
->sp
, mObj
);
1861 ++g
->sp
; SetObject(g
->sp
, string
);
1862 ++g
->sp
; SetObject(g
->sp
, string
);
1863 runInterpreter(g
, method
, 3);
1864 g
->canCallOS
= false;
1866 pthread_mutex_unlock (&gLangMutex
);
1868 } else return false; // handle the link in the responder
1874 ////////////////////
1875 SCView
* NewSCMovieView(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
1877 return new SCMovieView(inParent
, inObj
, inBounds
);
1880 SCMovieView
::SCMovieView(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
1881 : SCView(inParent
, inObj
, inBounds
)
1883 NSRect matrect
= SCtoNSRect(getDrawBounds());
1884 mMovieView
= [[QTMovieView alloc
] initWithFrame
:matrect
];
1885 [mMovieView setStepButtonsVisible
:YES
];
1886 [mMovieView setTranslateButtonVisible
:YES
];
1887 NSView
*view
= mTop
->GetNSView();
1888 [view addSubview
: mMovieView
];
1890 setVisibleFromParent();
1893 SCMovieView
::~
SCMovieView()
1895 [mMovieView removeFromSuperview
];
1896 [mMovieView release
];
1899 void SCMovieView
::setBounds(SCRect screct
)
1901 [[mMovieView superview
] setNeedsDisplayInRect
:[mMovieView frame
]];
1903 if(!(mParent
->isSubViewScroller())){
1904 SCRect pbounds
= mParent
->getLayout().bounds
;
1905 mLayout.bounds.x
= mBounds.x
+ pbounds.x
;
1906 mLayout.bounds.y
= mBounds.y
+ pbounds.y
;
1907 mLayout.bounds.width
= mBounds.width
;
1908 mLayout.bounds.height
= mBounds.height
;
1910 mLayout.bounds
= mBounds
;
1913 [mMovieView setFrame
: SCtoNSRect(mLayout.bounds
)];
1914 [mMovieView setBounds
: SCtoNSRect(mBounds
)]; //?
1915 [mMovieView setNeedsDisplay
: YES
];
1918 int SCMovieView
::setProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
1921 char *name
= symbol
->name
;
1923 if (strcmp(name
, "visible")==0) {
1924 bool visible
= IsTrue(slot
);
1926 setVisibleFromParent();
1930 if (strcmp(name
, "stop")==0) {
1935 if (strcmp(name
, "start")==0) {
1939 if (strcmp(name
, "stepForward")==0) {
1940 [mMovie stepForward
];
1943 if (strcmp(name
, "stepBack")==0) {
1944 [mMovie stepBackward
];
1948 if (strcmp(name, "resizeWithMagnification")==0) {
1950 err = slotFloatVal(slot, &mag);
1952 [mMovieView resizeWithMagnification: mag];
1953 NSSize size = [mMovieView sizeForMagnification: mag];
1954 mBounds.width = size.width;
1955 mBounds.height = size.height;
1959 if (strcmp(name
, "bounds")==0) {
1961 err
= slotGetSCRect(slot
, &screct
);
1962 if (err
) return err
;
1967 if (strcmp(name
, "setMovie")==0) {
1968 if(!isKindOfSlot(slot
, class_string
)) return errWrongType
;
1969 PyrString
* pstring
= slotRawString(slot
);
1970 if(!pstring
) return errNone
;
1971 NSString
*string
= [NSString stringWithCString
:pstring
->s encoding
:[NSString defaultCStringEncoding
]];
1972 string
= [string substringToIndex
:pstring
->size
];
1973 NSURL
* url
= [[NSURL alloc
] initFileURLWithPath
: string
];
1974 QTMovie
*movie
= [[QTMovie alloc
] initWithURL
: url error
:nil];
1975 if(!movie
) return errFailed
;
1976 //check for current movie:
1977 QTMovie
*old_movie
= [mMovieView movie
];
1978 [mMovieView setMovie
: movie
];
1980 [old_movie release
];
1985 mTime
= [movie currentTime
];
1990 if (strcmp(name
, "setMuted")==0) {
1991 if(IsTrue(slot
))[mMovie setMuted
: YES
];
1992 else [mMovie setMuted
: NO
];
1996 if (strcmp(name
, "setEditable")==0) {
1997 if(IsTrue(slot
))[mMovieView setEditable
: YES
];
1998 else [mMovieView setEditable
: NO
];
2002 if (strcmp(name
, "setPlaysSelectionOnly")==0) {
2003 [mMovie setAttribute
:[NSNumber numberWithBool
:IsTrue(slot
)] forKey
:QTMoviePlaysSelectionOnlyAttribute
];
2007 if (strcmp(name
, "setRate")==0) {
2009 err
= slotFloatVal(slot
, &rate
);
2011 [mMovie setRate
:rate
];
2014 if (strcmp(name
, "setVolume")==0) {
2016 err
= slotFloatVal(slot
, &vol
);
2018 [mMovie setVolume
:vol
];
2021 if (strcmp(name
, "setLoopMode")==0) {
2023 err
= slotIntVal(slot
, &mode
);
2025 NSMutableDictionary
*dict
= [NSMutableDictionary dictionaryWithObjectsAndKeys
: [NSNumber numberWithBool
:NO
], QTMovieLoopsBackAndForthAttribute
, [NSNumber numberWithBool
:NO
], QTMovieLoopsAttribute
, nil];
2028 case 0: [dict setObject
:[NSNumber numberWithBool
:YES
] forKey
:QTMovieLoopsBackAndForthAttribute
]; break;
2029 case 1: [dict setObject
:[NSNumber numberWithBool
:YES
] forKey
:QTMovieLoopsAttribute
]; break;
2033 [mMovie setMovieAttributes
:dict
];
2036 if (strcmp(name
, "gotoEnd")==0) {
2041 if (strcmp(name
, "gotoBeginning")==0) {
2042 [mMovie gotoBeginning
];
2046 if (strcmp(name, "showControllerAndAdjustSize")==0) {
2047 if(!isKindOfSlot(slot, class_array)) return errWrongType;
2048 PyrSlot *slots = slotRawObject(slot)->slots;
2050 if(IsTrue(slots+0)) showC=YES;
2052 if(IsTrue(slots+1)) adjust=YES;
2054 [mMovieView setControllerVisible:showC];
2055 //[mMovieView showController: showC adjustingSize: adjust];
2059 if (strcmp(name
, "copy")==0) {
2060 [mMovieView copy
: NULL
];
2063 if (strcmp(name
, "clear")==0) {
2064 [mMovieView
delete: NULL
];
2067 if (strcmp(name
, "cut")==0) {
2068 [mMovieView cut
: NULL
];
2071 if (strcmp(name
, "paste")==0) {
2072 [mMovieView paste
: NULL
];
2076 if (strcmp(name
, "setCurrentTime")==0) {
2078 err
= slotFloatVal(slot
, &time
);
2080 QTTime qttime
= mTime
;
2081 qttime.timeValue
= time
* qttime.timeScale
;
2082 [mMovie setCurrentTime
:qttime
];
2086 return SCView
::setProperty(symbol
, slot
);
2089 int SCMovieView
::getProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
2091 char *name
= symbol
->name
;
2092 //GetMovieDuration([[mMovieView movie] QTMovie]);
2093 if (strcmp(name
, "getCurrentTime")==0) {
2095 //post("timescale: %d \n", mTimeRecord.scale);
2096 QTTime qt_time
= [mMovie currentTime
];
2097 time
= (float) ((float)qt_time.timeValue
/ qt_time.timeScale
);
2098 SetFloat(slot
, time
);
2101 return SCView
::getProperty(symbol
, slot
);
2104 void SCMovieView
::setVisibleFromParent()
2106 if(mVisible
&& mParent
->isVisible()) {
2107 [mMovieView setHidden
:NO
];
2109 [mMovieView setHidden
:YES
];
2111 [mMovieView setNeedsDisplay
:YES
];
2112 NSRect frame
= [mMovieView frame
];
2113 [mMovieView setFrame
: NSInsetRect(frame
,1,1)];
2114 [mMovieView setFrame
: frame
];
2119 extern PyrSymbol
*s_proto
, *s_parent
;
2120 extern int ivxIdentDict_array
, ivxIdentDict_size
, ivxIdentDict_parent
, ivxIdentDict_proto
, ivxIdentDict_know
;
2121 int identDictPut(struct VMGlobals
*g
, PyrObject
*dict
, PyrSlot
*key
, PyrSlot
*value
);
2122 extern PyrClass
*class_identdict
;
2125 SCQuartzComposerView by Scott Wilson
2126 Copyright (c) 2007 Scott Wilson. All rights reserved.
2127 Development funded in part by the Arts and Humanites Research Council http://www.ahrc.ac.uk/
2130 SCView
* NewSCQuartzComposerView(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
2132 return new SCQuartzComposerView(inParent
, inObj
, inBounds
);
2135 SCQuartzComposerView
::SCQuartzComposerView(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
2136 : SCView(inParent
, inObj
, inBounds
)
2138 NSRect matrect
= SCtoNSRect(getDrawBounds());
2139 mQCView
= [[QCView alloc
] initWithFrame
:matrect
];
2140 [mQCView setEventForwardingMask
: NSAnyEventMask
];
2141 NSView
*view
= mTop
->GetNSView();
2142 [view addSubview
: mQCView
];
2144 setVisibleFromParent();
2147 SCQuartzComposerView
::~
SCQuartzComposerView()
2149 [mQCView removeFromSuperview
];
2154 void SCQuartzComposerView
::setBounds(SCRect screct
)
2156 [[mQCView superview
] setNeedsDisplayInRect
:[mQCView frame
]];
2158 if(!(mParent
->isSubViewScroller())){
2159 SCRect pbounds
= mParent
->getLayout().bounds
;
2160 mLayout.bounds.x
= mBounds.x
+ pbounds.x
;
2161 mLayout.bounds.y
= mBounds.y
+ pbounds.y
;
2162 mLayout.bounds.width
= mBounds.width
;
2163 mLayout.bounds.height
= mBounds.height
;
2165 mLayout.bounds
= mBounds
;
2167 [mQCView setFrame
: SCtoNSRect(mLayout.bounds
)];
2168 [mQCView setNeedsDisplay
: YES
];
2173 int SCQuartzComposerView
::setProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
2175 char *name
= symbol
->name
;
2177 if (strcmp(name
, "visible")==0) {
2178 bool visible
= IsTrue(slot
);
2179 // if(visible && mParent->isVisible())
2181 // [mQCView setHidden:NO];
2185 // [mQCView setHidden:YES];
2186 // mTop->resetFocus();
2189 setVisibleFromParent();
2193 if (strcmp(name
, "bounds")==0) {
2195 int err
= slotGetSCRect(slot
, &screct
);
2196 if (err
) return err
;
2202 if (strcmp(name
, "loadCompositionFromFile")==0) {
2203 if(!isKindOfSlot(slot
, class_string
)) return errWrongType
;
2204 PyrString
* pstring
= slotRawString(slot
);
2205 if(!pstring
) return errNone
;
2206 NSString
*string
= [[NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
] ] substringToIndex
: pstring
->size
];
2207 BOOL success
= [mQCView loadCompositionFromFile
: string
];
2208 if(!success
) return errFailed
;
2212 if (strcmp(name
, "stop")==0) {
2213 [mQCView stopRendering
];
2217 if (strcmp(name
, "start")==0) {
2218 BOOL success
= [mQCView startRendering
];
2219 if(!success
) return errFailed
;
2223 //// doesn't seem to work ; fix later
2224 // if (strcmp(name, "erase")==0) {
2229 // if (strcmp(name, "eraseColor")==0) {
2231 // int err = slotColorVal(slot, &rgb);
2232 // if (err) return err;
2233 // NSColor *color = [NSColor colorWithCalibratedRed: rgb.red green: rgb.green blue: rgb.blue alpha: rgb.alpha];
2234 // //NSLog(@"color: %@", color);
2235 // //NSColor *color = [NSColor blueColor];
2236 // [mQCView setEraseColor: color];
2241 if (strcmp(name
, "setMaxRenderingFrameRate")==0) {
2243 int err
= slotFloatVal(slot
, &rate
);
2244 if (err
) return err
;
2245 [mQCView setMaxRenderingFrameRate
: rate
];
2249 if (strcmp(name
, "setInputValue")==0) {
2250 if(!isKindOfSlot(slot
, class_array
)) return errWrongType
;
2251 PyrSlot
*slots
= slotRawObject(slot
)->slots
;
2252 PyrSymbol
*keysymbol
;
2253 int err
= slotSymbolVal(slots
+ 0, &keysymbol
);
2254 if (err
) return err
;
2256 NSString
*key
= [[NSString alloc
] initWithCString
: keysymbol
->name encoding
: NSASCIIStringEncoding
];
2257 if(![[mQCView inputKeys
] containsObject
: key
]) {
2259 //post("There is no port with key \"%s\".\n\n", [key cString]);
2263 id nsObject
= getNSObjectForSCObject(slots
+ 1, &err
);
2264 if(!nsObject
) {[key release
]; return err
;}
2265 BOOL success
= [mQCView setValue
: nsObject forInputKey
: key
];
2267 if(!success
) return errFailed
;
2272 return SCView
::setProperty(symbol
, slot
);
2275 id SCQuartzComposerView
::getNSObjectForSCObject(PyrSlot
*scobject
, int *returnErr
) {
2278 // find the value type and set appropriately
2279 if(IsFloat(scobject
)) { // it's a float
2281 err
= slotFloatVal(scobject
, &val
);
2282 if (err
) {returnErr
= &err
; return NULL
;}
2283 NSNumber
*returnObject
= [NSNumber numberWithFloat
: val
];
2284 if(!returnObject
) { err
= errFailed
; returnErr
= &err
; return NULL
;}
2285 return returnObject
;
2286 } else if(IsInt(scobject
)) { // it's an int
2288 err
= slotIntVal(scobject
, &val
);
2289 if (err
) {returnErr
= &err
; return NULL
;}
2290 NSNumber
*returnObject
= [NSNumber numberWithInt
: val
];
2291 if(!returnObject
) { err
= errFailed
; returnErr
= &err
; return NULL
;}
2292 return returnObject
;
2293 } else if(IsTrue(scobject
)) { // it's bool true
2294 NSNumber
*returnObject
= [NSNumber numberWithBool
: YES
];
2295 if(!returnObject
) { err
= errFailed
; returnErr
= &err
; return NULL
;}
2296 return returnObject
;
2297 } else if(IsFalse(scobject
)) { // it's bool false
2298 NSNumber
*returnObject
= [NSNumber numberWithBool
: NO
];
2299 if(!returnObject
) { err
= errFailed
; returnErr
= &err
; return NULL
;}
2300 return returnObject
;
2301 } else if(isKindOfSlot(scobject
, s_string
->u.classobj
)) { // it's a string
2302 PyrString
*string
= slotRawString(scobject
);
2303 if(string
->size
== 0) { err
= errFailed
; returnErr
= &err
; return NULL
;}
2304 NSString
*returnObject
= [NSString stringWithCString
: string
->s encoding
:[NSString defaultCStringEncoding
]];
2305 returnObject
= [returnObject substringToIndex
: string
->size
];
2306 if(!returnObject
) { err
= errFailed
; returnErr
= &err
; return NULL
;}
2307 return returnObject
;
2308 } else if(isKindOfSlot(scobject
, s_color
->u.classobj
)) { // it's a color
2310 err
= slotColorVal(scobject
, &rgb
);
2311 if (err
) {returnErr
= &err
; return NULL
;}
2312 NSColor
*returnObject
= [NSColor colorWithCalibratedRed
: rgb.red green
: rgb.green blue
: rgb.blue alpha
: rgb.alpha
];
2313 if(!returnObject
) { err
= errFailed
; returnErr
= &err
; return NULL
;}
2314 return returnObject
;
2315 } else if(isKindOfSlot(scobject
, s_identitydictionary
->u.classobj
)) { // it's a structure (dict)
2317 array
= slotRawObject(&(slotRawObject(scobject
)->slots
[ivxIdentDict_array
]));
2318 if (!isKindOf((PyrObject
*)array
, class_array
)) { err
= errFailed
; returnErr
= &err
; return NULL
;}
2319 NSMutableDictionary
*structure
= [NSMutableDictionary dictionary
];
2320 int len
= array
->size
;
2322 for(int i
=0; i
<len
; i
=i
+2){
2323 PyrSlot
*element
= array
->slots
+i
;
2324 if(!IsNil(element
)) {
2325 PyrSymbol
*keysymbol
;
2326 err
= slotSymbolVal(element
, &keysymbol
);
2327 if (err
) {returnErr
= &err
; return NULL
;}
2328 NSString
*key
= [NSString stringWithCString
: keysymbol
->name encoding
: NSASCIIStringEncoding
];
2330 id innerSCObject
= getNSObjectForSCObject(element
+ 1, &innerErr
);
2331 if(!innerSCObject
) { returnErr
= &innerErr
; return NULL
;}
2332 [structure setObject
: innerSCObject forKey
: key
];
2338 } else if(isKindOfSlot(scobject
, class_array
)) { // it's a structure (array)
2339 PyrSlot
*array
= scobject
;
2340 int len
= slotRawObject(array
)->size
;
2341 NSMutableArray
*structure
= [NSMutableArray arrayWithCapacity
: (unsigned)len
];
2343 for(int i
=0; i
<len
; i
++){
2344 PyrSlot
*element
= slotRawObject(array
)->slots
+i
;
2346 id innerSCObject
= getNSObjectForSCObject(element
, &innerErr
);
2347 if(!innerSCObject
) { returnErr
= &innerErr
; return NULL
;}
2348 [structure addObject
: innerSCObject
];
2354 } else if(isKindOfSlot(scobject
, s_scimage
->u.classobj
)) { // it's an SCImage : )
2355 SCImage
*scimage
= (SCImage
*)slotRawPtr(slotRawObject(scobject
)->slots
);
2357 if([scimage isAccelerated
])
2358 return [scimage ciimage
];
2360 return [scimage nsimage
];
2363 post("SCQuartzComposerView: invalid SCImage as input port !");
2369 err
= errWrongType
; // it's something else...
2376 int SCQuartzComposerView
::getProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
2378 char *name
= symbol
->name
;
2379 if (strcmp(name
, "getOutputValue")==0) {
2380 PyrSymbol
*keysymbol
;
2381 int err
= slotSymbolVal(slot
, &keysymbol
);
2382 if (err
) return err
;
2384 NSString
*key
= [NSString stringWithCString
: keysymbol
->name encoding
: NSASCIIStringEncoding
];
2385 if(![[mQCView outputKeys
] containsObject
: key
]) {
2386 //post("There is no port with key \"%s\".\n\n", [key cString]);
2390 NSDictionary
*outputAttributes
= [[mQCView attributes
] objectForKey
: key
];
2391 NSString
*type
= [outputAttributes objectForKey
:QCPortAttributeTypeKey
];
2393 id nsObject
= [mQCView valueForOutputKey
: key
];
2394 err
= getSCObjectForNSObject(slot
, nsObject
, type
);
2395 if (err
) return err
;
2398 } else if(strcmp(name
, "getInputValue")==0) {
2399 PyrSymbol
*keysymbol
;
2400 int err
= slotSymbolVal(slot
, &keysymbol
);
2401 if (err
) return err
;
2403 NSString
*key
= [NSString stringWithCString
: keysymbol
->name encoding
: NSASCIIStringEncoding
];
2404 if(![[mQCView inputKeys
] containsObject
: key
]) {
2405 //post("There is no port with key \"%s\".\n\n", [key cString]);
2409 NSDictionary
*inputAttributes
= [[mQCView attributes
] objectForKey
: key
];
2410 NSString
*type
= [inputAttributes objectForKey
:QCPortAttributeTypeKey
];
2412 id nsObject
= [mQCView valueForInputKey
: key
];
2413 err
= getSCObjectForNSObject(slot
, nsObject
, type
);
2414 if (err
) return err
;
2417 } else if(strcmp(name
, "getInputKeys")==0) {
2418 NSArray
* inputKeys
= [mQCView inputKeys
];
2419 int size
= [inputKeys count
];
2420 VMGlobals
*g
= gMainVMGlobals
;
2421 PyrObject
* array
= newPyrArray(g
->gc
, size
, 0, true);
2422 SetObject(slot
, array
);
2424 for (int i
=0; i
<size
; ++i
) {
2425 NSString
*name
= [inputKeys objectAtIndex
: i
];
2426 PyrString
*string
= newPyrString(g
->gc
, [name UTF8String
], 0, true);
2427 SetObject(array
->slots
+ array
->size
, string
);
2429 g
->gc
->GCWrite(array
, string
);
2434 } else if(strcmp(name
, "getOutputKeys")==0) {
2435 NSArray
* inputKeys
= [mQCView outputKeys
];
2436 int size
= [inputKeys count
];
2437 VMGlobals
*g
= gMainVMGlobals
;
2438 PyrObject
* array
= newPyrArray(g
->gc
, size
, 0, true);
2439 SetObject(slot
, array
);
2441 for (int i
=0; i
<size
; ++i
) {
2442 NSString
*name
= [inputKeys objectAtIndex
: i
];
2443 PyrString
*string
= newPyrString(g
->gc
, [name UTF8String
], 0, true);
2444 SetObject(array
->slots
+ array
->size
, string
);
2446 g
->gc
->GCWrite(array
, string
);
2452 return SCView
::getProperty(symbol
, slot
);
2455 int SCQuartzComposerView
::getSCObjectForNSObject(PyrSlot
*slot
, id nsObject
, NSString
*type
)
2457 if([type isEqualToString
:QCPortTypeBoolean
]) {
2458 SetBool(slot
, [nsObject boolValue
]);
2460 } else if([type isEqualToString
:QCPortTypeIndex
]) {
2461 SetInt(slot
, [nsObject intValue
]);
2463 } else if([type isEqualToString
:QCPortTypeNumber
]) {
2464 SetFloat(slot
, [nsObject floatValue
]);
2466 } else if([type isEqualToString
:QCPortTypeString
]) {
2467 const char * cstr
= [nsObject UTF8String
];
2468 VMGlobals
*g
= gMainVMGlobals
;
2469 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
2470 SetObject(slot
, string
);
2472 } else if([type isEqualToString
:QCPortTypeColor
]) {
2474 VMGlobals
*g
= gMainVMGlobals
;
2475 PyrObject
* colorObj
= instantiateObject(g
->gc
, s_color
->u.classobj
, 0, false, true);
2476 SCColor rgb
= SCMakeColor([nsObject redComponent
], [nsObject greenComponent
], [nsObject blueComponent
], [nsObject alphaComponent
]);
2477 SetObject(slot
, colorObj
);
2478 int err
= setSlotColor(slot
, &rgb
);
2479 if (err
) { return err
;}
2481 } else if([type isEqualToString
:QCPortTypeStructure
]) {
2482 //NSLog(@"QCPortTypeStructure");
2483 //NSLog(@"class: %@", [nsObject class]);
2485 // for the moment QC seems to deal with all internal structures as NSCFDictionary
2486 // but check here to be safe
2487 if([nsObject isKindOfClass
: [NSDictionary
class]]){
2488 //NSLog(@"it's a dict");
2489 PyrObject
*dict
, *array
;
2490 VMGlobals
*g
= gMainVMGlobals
;
2492 dict
= instantiateObject(g
->gc
, class_identdict
, 5, true, false);
2493 array
= newPyrArray(g
->gc
, 4, 0, false);
2495 nilSlots(array
->slots
, array
->size
);
2496 SetObject(dict
->slots
+ ivxIdentDict_array
, array
);
2497 g
->gc
->GCWrite(dict
, array
);
2498 SetObject(slot
, dict
);
2500 NSEnumerator
*enumerator
= [nsObject keyEnumerator
];
2503 while ((key
= [enumerator nextObject
])) {
2504 //NSLog(@"key class: %@", [key class]);
2505 id innerNSObject
= [nsObject objectForKey
: key
];
2506 //NSLog(@"innerNSObject: %@", innerNSObject);
2508 NSString
*innerType
;
2510 if([innerNSObject isKindOfClass
: [NSNumber
class]]){
2511 //NSLog(@"objCType: %s", [innerNSObject objCType]);
2512 if(!strcmp([innerNSObject objCType
], @encode(BOOL))) {
2514 innerType
= QCPortTypeBoolean
;
2515 } else if(!strcmp([innerNSObject objCType
], @encode(int))) {
2516 innerType
= QCPortTypeIndex
;
2517 } else innerType
= QCPortTypeNumber
;
2518 } else if([innerNSObject isKindOfClass
: [NSColor
class]]){
2520 innerType
= QCPortTypeColor
;
2521 } else if([innerNSObject isKindOfClass
: [NSString
class]]){
2523 innerType
= QCPortTypeString
;
2524 } else if([innerNSObject isKindOfClass
: [NSArray
class]] ||
[innerNSObject isKindOfClass
: [NSDictionary
class]]){
2525 //NSLog(@"Structure");
2526 innerType
= QCPortTypeStructure
;
2527 } else return errWrongType
; // it's something else
2529 //NSLog(@"innerObject Class: %@", [innerNSObject class]);
2530 int err
= getSCObjectForNSObject(&innerSlot
, innerNSObject
, innerType
);
2534 SetSymbol(&outKey
, getsym([key cStringUsingEncoding
:[NSString defaultCStringEncoding
]]));
2535 err
= identDictPut(g
, dict
, &outKey
, &innerSlot
);
2544 else if([type isEqualToString
:QCPortTypeImage
]) { // SCImage
2545 NSImage
*nsimage
= (NSImage
*)nsObject
;
2547 post("SCQuartzComposerView: bad return value as QCPortTypeImage");
2549 SCImage
*scimage
= [[SCImage alloc
]initWithNSImage
:nsimage
];
2551 VMGlobals
*g
= gMainVMGlobals
;
2552 PyrObject
*object
= newPyrSCImage(g
); // should be garbage collected
2554 PyrSlot
*slots
= object
->slots
;
2555 SetObject(slot
, object
);
2556 SetPtr(slots
+ 0, scimage
);
2557 SetFloat(slots
+ 1, (float)[scimage width
]);
2558 SetFloat(slots
+ 2, (float)[scimage height
]);
2563 post("SCQuartzComposerView: failed NSImage to SCImage conversion !");
2566 return errWrongType
; // it's something else
2571 void SCQuartzComposerView
::setVisibleFromParent()
2573 if(mVisible
&& mParent
->isVisible()) {
2574 [mQCView setHidden
:NO
];
2577 [mQCView setHidden
:YES
];
2583 ////////////////////
2584 SCView
* NewSCWebView(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
2586 return new SCWebView(inParent
, inObj
, inBounds
);
2589 SCWebView
::SCWebView(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
2590 : SCView(inParent
, inObj
, inBounds
)
2592 NSRect matrect
= SCtoNSRect(getDrawBounds());
2593 //NSLog(@"bounds %@", NSStringFromRect(matrect));
2594 mWebView
= [[SCNSWebView alloc
] initWithFrame
:matrect frameName
:nil groupName
: nil];
2595 [mWebView initVars
];
2596 NSView
*view
= mTop
->GetNSView();
2597 flipView
= [[view window
] contentView
];
2598 if (![flipView isKindOfClass
: [SCNSFlippedView
class]] ) {
2599 flipView
= [[SCNSFlippedView alloc
] initWithFrame
:[view frame
]]; // a wrapper view hack to get coords right
2601 [view setAutoresizingMask
: 63];
2602 [flipView setAutoresizesSubviews
:YES
];
2603 [[view window
] setContentView
:flipView
];
2604 [flipView addSubview
:view
];
2606 [flipView retain
]; // increment the retain count
2608 [view addSubview
:mWebView
];
2610 [mWebView setEditingDelegate
:mWebView
];
2611 [mWebView setFrameLoadDelegate
:mWebView
];
2612 [mWebView setPolicyDelegate
:mWebView
];
2613 //[mWebView setUIDelegate:mWebView];
2615 [mWebView setSCObject
: this];
2617 [mWebView setFocusRingType
:NSFocusRingTypeNone
];
2618 [mWebView setEnterExecutesSelection
:YES
];
2619 [mWebView setPreferencesIdentifier
:@
"SuperCollider"];
2621 setVisibleFromParent();
2624 SCWebView
::~
SCWebView()
2626 [mWebView removeFromSuperview
];
2628 [[SCVirtualMachine sharedInstance
] removeDeferredOperationsFor
:mWebView
];
2630 if ([flipView retainCount
] == 1) { // if nobody else needs this wrapperView, clean it up
2631 NSView
*view
= mTop
->GetNSView();
2632 [[view window
] setContentView
:view
];
2634 [flipView removeFromSuperview
];
2637 [flipView release
]; // otherwise just decrement the retain count
2642 void SCWebView
::setBounds(SCRect screct
)
2645 mBounds.x
== screct.x
&&
2646 mBounds.x
== screct.y
&&
2647 mBounds.width
== screct.width
&&
2648 mBounds.height
== screct.height
2649 ) { // in case - prevent a refresh if the bounds are the same
2654 if(!(mParent
->isSubViewScroller())){
2655 SCRect pbounds
= mParent
->getLayout().bounds
;
2656 mLayout.bounds.x
= mBounds.x
+ pbounds.x
;
2657 mLayout.bounds.y
= mBounds.y
+ pbounds.y
;
2658 mLayout.bounds.width
= mBounds.width
;
2659 mLayout.bounds.height
= mBounds.height
;
2661 mLayout.bounds
= mBounds
;
2664 [mWebView setFrame
: SCtoNSRect(mLayout.bounds
)];
2667 void SCWebView
::doOnLoadAction()
2669 pthread_mutex_lock (&gLangMutex
);
2671 PyrSymbol
*method
= getsym("didLoad");
2672 VMGlobals
*g
= gMainVMGlobals
;
2673 g
->canCallOS
= true;
2674 ++g
->sp
; SetObject(g
->sp
, mObj
);
2675 runInterpreter(g
, method
, 1);
2676 g
->canCallOS
= false;
2678 pthread_mutex_unlock (&gLangMutex
);
2681 void SCWebView
::doLoadFailedAction()
2683 pthread_mutex_lock (&gLangMutex
);
2685 PyrSymbol
*method
= getsym("didFail");
2686 VMGlobals
*g
= gMainVMGlobals
;
2687 g
->canCallOS
= true;
2688 ++g
->sp
; SetObject(g
->sp
, mObj
);
2689 runInterpreter(g
, method
, 1);
2690 g
->canCallOS
= false;
2692 pthread_mutex_unlock (&gLangMutex
);
2695 void SCWebView
::doLinkClickedAction(PyrString
* pstring
)
2697 pthread_mutex_lock (&gLangMutex
);
2699 PyrSymbol
*method
= getsym("linkActivated");
2700 VMGlobals
*g
= gMainVMGlobals
;
2701 g
->canCallOS
= true;
2702 ++g
->sp
; SetObject(g
->sp
, mObj
);
2703 ++g
->sp
; SetObject(g
->sp
, pstring
);
2704 runInterpreter(g
, method
, 2);
2705 g
->canCallOS
= false;
2707 pthread_mutex_unlock (&gLangMutex
);
2710 int SCWebView
::setProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
2713 char *name
= symbol
->name
;
2715 if (strcmp(name
, "url")==0) {
2716 if(!isKindOfSlot(slot
, class_string
)) return errWrongType
;
2717 PyrString
* pstring
= slotRawString(slot
);
2718 if(!pstring
) return errFailed
;
2719 [mWebView resetLoadCount
];
2720 NSString
*path
= [[NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
]] substringToIndex
: pstring
->size
];
2721 [[mWebView mainFrame
] loadRequest
:[NSURLRequest requestWithURL
:[NSURL URLWithString
:path
]]];
2725 if (strcmp(name
, "visible")==0) {
2726 bool visible
= IsTrue(slot
);
2728 setVisibleFromParent();
2732 if (strcmp(name
, "bounds")==0) {
2734 err
= slotGetSCRect(slot
, &screct
);
2735 if (err
) return err
;
2740 if (strcmp(name
, "back")==0) {
2741 if([mWebView canGoBack
]) {
2742 [mWebView resetLoadCount
];
2743 SEL selector
= @selector(goBack
);
2744 NSInvocation
*invocation
= [NSInvocation invocationWithMethodSignature
:
2745 [mWebView methodSignatureForSelector
: selector
]];
2746 [invocation setTarget
:mWebView
];
2747 [invocation setSelector
: selector
];
2749 [[SCVirtualMachine sharedInstance
] defer
: invocation
];
2754 if (strcmp(name
, "forward")==0) {
2755 if([mWebView canGoForward
]) {
2756 [mWebView resetLoadCount
];
2757 SEL selector
= @selector(goForward
);
2758 NSInvocation
*invocation
= [NSInvocation invocationWithMethodSignature
:
2759 [mWebView methodSignatureForSelector
: selector
]];
2760 [invocation setTarget
:mWebView
];
2761 [invocation setSelector
: selector
];
2763 [[SCVirtualMachine sharedInstance
] defer
: invocation
];
2768 if (strcmp(name
, "reload")==0) {
2769 [mWebView resetLoadCount
];
2770 SEL selector
= @selector(reload
:);
2771 NSInvocation
*invocation
= [NSInvocation invocationWithMethodSignature
:
2772 [mWebView methodSignatureForSelector
: selector
]];
2773 [invocation setTarget
:mWebView
];
2774 [invocation setSelector
: selector
];
2775 [invocation setArgument
:&mWebView atIndex
:2];
2777 [[SCVirtualMachine sharedInstance
] defer
: invocation
];
2781 if (strcmp(name
, "html")==0) {
2782 if(!isKindOfSlot(slot
, class_string
)) return errWrongType
;
2783 PyrString
* pstring
= slotRawString(slot
);
2784 if(!pstring
) return errFailed
;
2785 [mWebView resetLoadCount
];
2786 NSString
*html
= [[NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
]] substringToIndex
: pstring
->size
];
2787 [[mWebView mainFrame
] loadHTMLString
:html baseURL
:nil];
2791 if (strcmp(name
, "handleLinks")==0) {
2792 bool handleLinks
= IsTrue(slot
);
2793 [mWebView setHandleLinks
: handleLinks
];
2797 if (strcmp(name
, "editable")==0) {
2798 bool editable
= IsTrue(slot
);
2799 [mWebView setEditable
: editable
];
2803 if (strcmp(name
, "findText")==0) {
2804 if(!isKindOfSlot(slot
, class_array
)) return errWrongType
;
2805 PyrSlot
*slots
=slotRawObject(slot
)->slots
;
2806 PyrSlot
*stringSlot
= slots
+0;
2807 if(!isKindOfSlot(stringSlot
, class_string
)) return errWrongType
;
2808 PyrString
* pstring
= slotRawString(stringSlot
);
2809 if(!pstring
) return errFailed
;
2810 NSString
*searchText
= [[NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
] ] substringToIndex
: pstring
->size
];
2812 PyrSlot
*dir
= slots
+1;
2813 bool goesForward
= IsFalse(dir
);
2815 [mWebView searchFor
:searchText direction
:goesForward caseSensitive
:NO wrap
:YES
];
2819 if (strcmp(name
, "enterExecutesSelection")==0) {
2820 if(IsTrue(slot
))[mWebView setEnterExecutesSelection
:YES
];
2821 else [mWebView setEnterExecutesSelection
:NO
];
2825 if (strcmp(name
, "fontFamily")==0) {
2826 if(!isKindOfSlot(slot
, class_array
)) return errWrongType
;
2827 PyrSlot
*slots
= slotRawObject(slot
)->slots
;
2828 if(!IsSym(slots
+0)) return errWrongType
;
2829 PyrString
* pstring
= slotRawString(slots
+1);
2830 if(!pstring
) return errFailed
;
2832 PyrSymbol
*genericFont
= slotRawSymbol(slots
+0);
2833 NSString
*specificFont
= [[NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
]] substringToIndex
: pstring
->size
];
2835 if (genericFont
== getsym("standard"))
2836 [[mWebView preferences
] setStandardFontFamily
: specificFont
];
2837 else if (genericFont
== getsym("fixed"))
2838 [[mWebView preferences
] setFixedFontFamily
: specificFont
];
2839 else if (genericFont
== getsym("serif"))
2840 [[mWebView preferences
] setSerifFontFamily
: specificFont
];
2841 else if (genericFont
== getsym("sansSerif"))
2842 [[mWebView preferences
] setSansSerifFontFamily
: specificFont
];
2843 else if (genericFont
== getsym("cursive"))
2844 [[mWebView preferences
] setCursiveFontFamily
: specificFont
];
2845 else if (genericFont
== getsym("fantasy"))
2846 [[mWebView preferences
] setFantasyFontFamily
: specificFont
];
2851 return SCView
::setProperty(symbol
, slot
);
2855 int SCWebView
::getProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
2857 char *name
= symbol
->name
;
2858 VMGlobals
*g
= gMainVMGlobals
;
2860 if (strcmp(name
, "url")==0) {
2861 NSString
*rawLocationString
= [mWebView stringByEvaluatingJavaScriptFromString
:@
"location.href;"];
2862 const char * cstr
= [rawLocationString UTF8String
];
2863 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
2864 SetObject(slot
, string
);
2868 if (strcmp(name
, "html")==0) {
2869 NSString
*html
= [mWebView stringByEvaluatingJavaScriptFromString
:@
"document.documentElement.outerHTML"];
2870 const char * cstr
= [html UTF8String
];
2871 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
2872 SetObject(slot
, string
);
2876 if (strcmp(name
, "plainText")==0) {
2877 NSString
*plainText
= [mWebView stringByEvaluatingJavaScriptFromString
:@
"document.body.innerText"];
2878 const char * cstr
= [plainText UTF8String
];
2879 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
2880 SetObject(slot
, string
);
2884 if (strcmp(name
, "selectedText")==0) {
2885 NSString
*selectedText
= [mWebView stringByEvaluatingJavaScriptFromString
:@
"(function (){return window.getSelection().toString();})();"];
2886 const char * cstr
= [selectedText UTF8String
];
2887 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
2888 SetObject(slot
, string
);
2892 if (strcmp(name
, "title")==0) {
2893 NSString
*rawLocationString
= [mWebView mainFrameTitle
];
2894 const char * cstr
= [rawLocationString UTF8String
];
2895 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
2896 SetObject(slot
, string
);
2900 return SCView
::getProperty(symbol
, slot
);
2904 void SCWebView
::setVisibleFromParent()
2906 if(mVisible
&& mParent
->isVisible()) {
2907 [mWebView setHidden
:NO
];
2909 [mWebView setHidden
:YES
];
2911 [mWebView setNeedsDisplay
:YES
];
2912 NSRect frame
= [mWebView frame
];
2913 [mWebView setFrame
: frame
];
2919 void SCWebView
::tabPrevFocus()
2921 mTop
->tabPrevFocus();
2923 void SCWebView
::tabNextFocus()
2925 //post("next focus\n");
2926 mTop
->tabNextFocus();
2929 void SCWebView
::mouseTrack(SCPoint where
, int modifiers
, NSEvent
*theEvent
)
2931 if (modifiers
& NSCommandKeyMask
) {
2937 ////////////////////
2939 ////////////////////
2940 SCView
* NewSCTextField(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
2942 return new SCTextField(inParent
, inObj
, inBounds
);
2945 SCTextField
::SCTextField(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
2946 : SCView(inParent
, inObj
, inBounds
)
2947 //: SCStaticText(inParent, inObj, inBounds)
2949 NSRect matrect
= SCtoNSRect(getDrawBounds());
2950 mTextField
= [[SCTextFieldResponder alloc
] initWithFrame
:matrect
];
2951 NSView
*view
= mTop
->GetNSView();
2952 [view addSubview
: mTextField
];
2954 [mTextField setFocusRingType
:NSFocusRingTypeNone
];
2955 //NSLog(@"SCTextField init\n");
2957 //mCocoaToLangAction = [SCTextFieldResponder alloc];
2958 [mTextField setSCView
: this];
2959 [mTextField setDelegate
: mTextField
];
2960 [mTextField setEditingInactive
:NO
];
2962 [mTextField setBordered
:NO
]; // for some reason, if we don't set this we can't have transparency
2963 [mTextField setDrawsBackground
:NO
]; // SCView will draw for us. This also allows 0 < alpha < 1
2965 [[mTextField cell
] setScrollable
:YES
];
2967 mBackground
= new SolidColorBackground(SCMakeColor(1.0,1.0,1.0, 1.0)); // default is white
2969 [mTextField registerForDraggedTypes
: [NSArray arrayWithObjects
: sSCObjType
, NSStringPboardType
, NSFilenamesPboardType
, nil]];
2970 //This is a hack, otherwise the mTextField always has focus even if makeFirstResponder: view is called...
2971 [mTextField setAcceptsFirstResponder
:NO
];
2972 setVisibleFromParent();
2975 SCTextField
::~
SCTextField()
2977 [mTextField removeFromSuperview
];
2978 [mTextField release
];
2981 void SCTextField
::setBounds(SCRect screct
)
2984 mBounds.x
== screct.x
&&
2985 mBounds.x
== screct.y
&&
2986 mBounds.width
== screct.width
&&
2987 mBounds.height
== screct.height
2988 ) { // in case - prevent a refresh if the bounds are the same
2992 //[[mTextField superview] setNeedsDisplayInRect:[mTextField frame]];
2994 if(!(mParent
->isSubViewScroller())){
2995 SCRect pbounds
= mParent
->getLayout().bounds
;
2996 mLayout.bounds.x
= mBounds.x
+ pbounds.x
;
2997 mLayout.bounds.y
= mBounds.y
+ pbounds.y
;
2998 mLayout.bounds.width
= mBounds.width
;
2999 mLayout.bounds.height
= mBounds.height
;
3001 mLayout.bounds
= mBounds
;
3004 [mTextField setFrame
: SCtoNSRect(mLayout.bounds
)];
3005 //[mTextField setNeedsDisplay: YES];
3008 int SCTextField
::setProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
3011 char *name
= symbol
->name
;
3013 if (strcmp(name
, "string")==0) {
3014 if(!isKindOfSlot(slot
, class_string
)) return errWrongType
;
3015 PyrString
* pstring
= slotRawString(slot
);
3016 if(!pstring
) return errNone
;
3017 NSString
*string
= [[NSString stringWithCString
: pstring
->s encoding
: [NSString defaultCStringEncoding
] ] substringToIndex
: pstring
->size
];
3018 [mTextField setStringValue
: string
];
3022 if (strcmp(name
, "visible")==0) {
3023 bool visible
= IsTrue(slot
);
3025 setVisibleFromParent();
3029 if (strcmp(name
, "font")==0) {
3033 font
= [NSFont controlContentFontOfSize
: 0.0 ];
3037 if (!(isKindOfSlot(slot
, s_font
->u.classobj
))) return errWrongType
;
3038 PyrSlot
*nameSlot
= slotRawObject(slot
)->slots
+0;
3039 PyrSlot
*sizeSlot
= slotRawObject(slot
)->slots
+1;
3041 if (IsNil(sizeSlot
)){
3042 size
= [[mTextField font
] pointSize
];
3044 int err
= slotFloatVal(sizeSlot
, &size
);
3045 if (err
) return err
;
3048 PyrString
*pstring
= slotRawString(nameSlot
);
3049 NSString
*fontName
= [NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
]];
3050 fontName
= [fontName substringToIndex
: pstring
->size
];
3051 if (!fontName
) return errFailed
;
3052 font
= [NSFont fontWithName
: fontName size
: size
];
3053 if (!font
) return errFailed
;
3056 [mTextField setFont
: font
];
3060 if (strcmp(name
, "stringColor")==0) {
3061 err
= slotColorVal(slot
, &mStringColor
);
3062 if (err
) return err
;
3063 NSColor
*color
= [NSColor colorWithCalibratedRed
: mStringColor.red
3064 green
: mStringColor.green
3065 blue
: mStringColor.blue
3066 alpha
: mStringColor.alpha
];
3067 [mTextField setTextColor
: color
];
3072 if (strcmp(name
, "bounds")==0) {
3074 err
= slotGetSCRect(slot
, &screct
);
3075 if (err
) return err
;
3080 if (strcmp(name
, "align")==0) {
3082 [[mTextField window
] endEditingFor
:mTextField
];
3083 if (slotRawSymbol(slot
)->name
[0] == 'l') [mTextField setAlignment
: NSLeftTextAlignment
];
3084 else if (slotRawSymbol(slot
)->name
[0] == 'r') [mTextField setAlignment
: NSRightTextAlignment
];
3085 else if (slotRawSymbol(slot
)->name
[0] == 'c') [mTextField setAlignment
: NSCenterTextAlignment
];
3086 else return errFailed
;
3088 //[mTextField display];
3090 err = slotIntVal(slot, &align);
3091 if (err) return err;
3098 if (strcmp(name
, "enabled")==0) {
3099 bool enabled
= IsTrue(slot
);
3100 if (mEnabled
!= enabled
) {
3102 [mTextField setEnabled
:(BOOL)enabled
];
3103 if (!mEnabled
) mTop
->resetFocus();
3109 //return SCStaticText::setProperty(symbol, slot);
3110 return SCView
::setProperty(symbol
, slot
);
3114 int SCTextField
::getProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
3116 char *name
= symbol
->name
;
3117 VMGlobals
*g
= gMainVMGlobals
;
3119 if (strcmp(name
, "string")==0) {
3120 NSString
* str
= [mTextField stringValue
];
3121 const char * cstr
= [str UTF8String
];
3122 PyrString
*string
= newPyrString(g
->gc
, cstr
, 0, true);
3123 SetObject(slot
, string
);
3126 if (strcmp(name
, "boxColor")==0) {
3127 return setSlotColor(slot
, &mBoxColor
);
3129 if (strcmp(name
, "stringColor")==0) {
3130 return setSlotColor(slot
, &mStringColor
);
3133 //return SCStaticText::getProperty(symbol, slot);
3134 return SCView
::getProperty(symbol
, slot
);
3138 void SCTextField
::setVisibleFromParent()
3140 if(mVisible
&& mParent
->isVisible()) {
3141 [mTextField setHidden
:NO
];
3143 [mTextField setHidden
:YES
];
3145 [mTextField setNeedsDisplay
:YES
];
3146 NSRect frame
= [mTextField frame
];
3147 [mTextField setFrame
: NSInsetRect(frame
,1,1)];
3148 [mTextField setFrame
: frame
];
3153 void SCTextField
::makeFocus(bool focus
)
3156 if (canFocus() && !isFocus()) {
3157 [mTextField setAcceptsFirstResponder
:YES
];
3159 // trick focus ring into drawing
3160 SEL sel
= @selector(setNeedsDisplay
:);
3161 NSMethodSignature
*sig
= [NSView instanceMethodSignatureForSelector
: sel
];
3162 NSInvocation
*anInvocation
= [NSInvocation invocationWithMethodSignature
: sig
];
3163 SCVirtualMachine
* scvm
= [SCVirtualMachine sharedInstance
];
3164 [anInvocation setTarget
: [mTextField superview
]];
3165 [anInvocation setSelector
: sel
];
3167 [anInvocation setArgument
: &flag atIndex
: 2];
3168 [scvm defer
: anInvocation
];
3172 [mTextField setAcceptsFirstResponder
:NO
];
3175 SCView
::makeFocus(focus
);
3178 void SCTextField
::tabPrevFocus()
3180 mTop
->tabPrevFocus();
3182 void SCTextField
::tabNextFocus()
3184 //post("next focus\n");
3185 mTop
->tabNextFocus();
3188 void SCTextField
::keyDown(int character
, int modifiers
, unsigned short keycode
)
3190 // when enter was pressed firstResponder was passed to the parent SCGraphView
3191 // this checks if keyDown was passed from there and if so starts to edit using the key pressed
3192 // We access the field editor as that's the receiving object while editing is active
3193 if([mTextField editingInactive
] && (character
!= 13 || character
!=3)) {
3194 //post("keydownEP\n");
3195 [[mTextField window
] makeFirstResponder
:mTextField
];
3196 unichar charVal
= (unichar
)character
;
3197 NSString
*charstring
= [[NSString alloc
] initWithCharacters
: &charVal length
: 1];
3198 NSText
*fieldEditor
= [[mTextField window
] fieldEditor
:YES forObject
:mTextField
];
3199 [fieldEditor setString
:charstring
];
3200 [charstring release
];
3201 [mTextField setEditingInactive
:NO
];
3203 SCView
::keyDown(character
, modifiers
, keycode
);
3206 extern PyrSymbol
* s_canReceiveDrag
;
3208 bool SCTextField
::canReceiveDrag()
3211 sendMessage(s_canReceiveDrag
, 0, 0, &result
);
3212 return IsTrue(&result
);
3215 NSDragOperation SCTextField
::draggingEntered()
3217 bool flag
= canReceiveDrag();
3218 mTop
->setDragView(flag ?
this : 0);
3219 [mTextField displayIfNeeded
];
3220 return flag ? NSDragOperationEvery
: NSDragOperationNone
;
3223 extern PyrSymbol
* s_receiveDrag
;
3225 BOOL SCTextField
::performDrag()
3227 bool flag
= canReceiveDrag();
3229 mTop
->setDragView(this);
3230 sendMessage(s_receiveDrag
, 0, 0, 0);
3231 mTop
->setDragView(0);
3233 mTop
->setDragView(0);
3235 [mTextField displayIfNeeded
];
3236 return flag ? YES
: NO
;
3239 void SCTextField
::mouseTrack(SCPoint where
, int modifiers
, NSEvent
*theEvent
)
3241 if (modifiers
& NSCommandKeyMask
) {
3246 extern PyrSymbol
*s_beginDrag
;
3248 void SCTextField
::beginDrag(SCPoint where
)
3250 sendMessage(s_beginDrag
, 0, 0, 0);
3254 NSString
*string
= 0;
3255 NSString
*label
= 0;
3256 pthread_mutex_lock (&gLangMutex
);
3258 VMGlobals
*g
= gMainVMGlobals
;
3259 int classVarIndex
= slotRawInt(&getsym("SCView")->u.classobj
->classVarIndex
);
3260 slotCopy(&slot
, &g
->classvars
->slots
[classVarIndex
]);
3261 slotCopy(&stringSlot
, &g
->classvars
->slots
[classVarIndex
+1]);
3262 if (isKindOfSlot(&stringSlot
, class_string
)) {
3263 PyrString
*pstring
= slotRawString(&stringSlot
);
3264 string
= [NSString stringWithCString
: pstring
->s encoding
:[NSString defaultCStringEncoding
]];
3265 string
= [string substringToIndex
: pstring
->size
];
3267 if(mDragLabel
) label
= mDragLabel
;
3269 pthread_mutex_unlock (&gLangMutex
);
3271 //mTop->beginDragCallback(where, &slot, string, label);
3272 NSPoint point
= NSMakePoint(where.x
, where.y
);
3273 [mTextField beginDragFrom
: point of
: &slot string
: string label
: label
];
3276 ////////////////////
3277 SCView
* NewSCNumberBox(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
3279 return new SCNumberBox(inParent
, inObj
, inBounds
);
3282 SCNumberBox
::SCNumberBox(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
3283 : SCTextField(inParent
, inObj
, inBounds
)
3284 //: SCStaticText(inParent, inObj, inBounds)
3286 [mTextField addNumberFormatter
];
3289 SCNumberBox
::~
SCNumberBox()
3293 int SCNumberBox
::setProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
3296 char *name
= symbol
->name
;
3298 if (strcmp(name
, "value")==0) {
3300 err
= slotDoubleVal(slot
, &value
);
3301 if (err
) return err
;
3302 [mTextField setDoubleValue
:value
];
3306 // if (strcmp(name, "clipLo")==0) {
3308 // err = slotDoubleVal(slot, &value);
3309 // if (err) return err;
3310 // [[mTextField formatter] setMinimum:[NSNumber numberWithDouble:value]];
3314 // if (strcmp(name, "clipHi")==0) {
3316 // err = slotDoubleVal(slot, &value);
3317 // if (err) return err;
3318 // [[mTextField formatter] setMaximum:[NSNumber numberWithDouble:value]];
3322 return SCTextField
::setProperty(symbol
, slot
);
3325 int SCNumberBox
::getProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
3327 char *name
= symbol
->name
;
3329 if (strcmp(name
, "value")==0) {
3330 double val
= [mTextField doubleValue
];
3331 SetFloat(slot
, val
);
3335 return SCTextField
::getProperty(symbol
, slot
);
3338 void SCNumberBox
::keyDown(int character
, int modifiers
, unsigned short keycode
)
3340 // test for arrows enter and return
3341 if([mTextField editingInactive
] && (character
== 63232 || character
== 63233 || character
== 63234 || character
== 63235 || character
== 3 || character
== 13)){
3342 SCView
::keyDown(character
, modifiers
, keycode
);
3344 SCTextField
::keyDown(character
, modifiers
, keycode
);
3348 ////////////////////
3349 SCView
* NewSCLevelIndicator(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
3351 return new SCLevelIndicator(inParent
, inObj
, inBounds
);
3354 SCLevelIndicator
::SCLevelIndicator(SCContainerView
*inParent
, PyrObject
* inObj
, SCRect inBounds
)
3355 : SCView(inParent
, inObj
, inBounds
)
3357 NSRect matrect
= SCtoNSRect(getDrawBounds());
3358 mLevelIndicator
= [[SCNSLevelIndicator alloc
] initWithFrame
:matrect
];
3359 NSView
*view
= mTop
->GetNSView();
3360 [view addSubview
: mLevelIndicator
];
3362 [[mLevelIndicator cell
] setLevelIndicatorStyle
:NSContinuousCapacityLevelIndicatorStyle
];
3363 [mLevelIndicator setMinValue
:0.0];
3364 [mLevelIndicator setMaxValue
:1.0];
3367 if(matrect.size.height
> matrect.size.width
) {
3368 [mLevelIndicator setBoundsRotation
: 90.0]; // vertical
3369 [mLevelIndicator setIsVertical
:YES
];
3370 [mLevelIndicator setNeedsDisplay
: YES
];
3372 } else mIsVertical
= false;
3378 mImage
= [[NSImage imageNamed
:@
"NSApplicationIcon"] retain
];
3381 setVisibleFromParent();
3384 SCLevelIndicator
::~
SCLevelIndicator()
3386 [mLevelIndicator removeFromSuperview
];
3387 [mLevelIndicator release
];
3391 void SCLevelIndicator
::setBounds(SCRect screct
)
3394 if(!(mParent
->isSubViewScroller())){
3395 SCRect pbounds
= mParent
->getLayout().bounds
;
3396 mLayout.bounds.x
= mBounds.x
+ pbounds.x
;
3397 mLayout.bounds.y
= mBounds.y
+ pbounds.y
;
3398 mLayout.bounds.width
= mBounds.width
;
3399 mLayout.bounds.height
= mBounds.height
;
3401 mLayout.bounds
= mBounds
;
3404 if(mBounds.height
> mBounds.width
) {
3405 [mLevelIndicator setBoundsRotation
: 90.0]; // vertical
3407 [mLevelIndicator setIsVertical
:YES
];
3409 [mLevelIndicator setBoundsRotation
: 0.0]; // horizontal
3410 mIsVertical
= false;
3411 [mLevelIndicator setIsVertical
:NO
];
3414 if([mLevelIndicator numberOfTickMarks
] > 0)
3415 mTickHeight
= [mLevelIndicator rectOfTickMarkAtIndex
:0].size.height
; // 0 will be major if there are any
3419 [mLevelIndicator setPeakSubtract
:mTickHeight
];
3422 [mLevelIndicator setFrame
: SCtoNSRect(mLayout.bounds
)];
3423 [mLevelIndicator setNeedsDisplay
: YES
];
3426 void SCLevelIndicator
::setImage()
3428 NSImage
* newImage
= nil;
3430 NSSize imageSize
= [mImage size
];
3431 float width
= imageSize.width
;
3432 float height
= imageSize.height
;
3434 SCRect bounds
= getDrawBounds();
3437 targetSize
= NSMakeSize(bounds.height
/ mNumSteps
, bounds.width
- mTickHeight
);
3439 targetSize
= NSMakeSize(bounds.width
/ mNumSteps
, bounds.height
- mTickHeight
);
3442 float targetWidth
= targetSize.width
;
3443 float targetHeight
= targetSize.height
;
3445 float scaleFactor
= 0.0;
3446 float scaledWidth
= targetWidth
;
3447 float scaledHeight
= targetHeight
;
3449 NSPoint newPoint
= NSMakePoint(0,0);
3451 if ( NSEqualSizes( imageSize
, targetSize
) == NO
)
3453 float widthFactor
, heightFactor
;
3455 widthFactor
= targetHeight
/ width
;
3456 heightFactor
= targetWidth
/ height
;
3458 widthFactor
= targetWidth
/ width
;
3459 heightFactor
= targetHeight
/ height
;
3462 if ( widthFactor
< heightFactor
)
3463 scaleFactor
= widthFactor
;
3465 scaleFactor
= heightFactor
;
3467 scaledWidth
= width
* scaleFactor
;
3468 scaledHeight
= height
* scaleFactor
;
3471 if ( widthFactor
< heightFactor
)
3472 newPoint.y
= (targetWidth
- scaledHeight
) * 0.5;
3473 else if ( widthFactor
> heightFactor
)
3474 newPoint.x
= (targetHeight
- scaledWidth
) * 0.5;
3476 if ( widthFactor
< heightFactor
)
3477 newPoint.y
= (targetHeight
- scaledHeight
) * 0.5;
3478 else if ( widthFactor
> heightFactor
)
3479 newPoint.x
= (targetWidth
- scaledWidth
) * 0.5;
3483 //NSLog(@"targetSize: %@", NSStringFromSize(targetSize));
3485 // create a new image to draw into
3486 newImage
= [[NSImage alloc
] initWithSize
:targetSize
];
3488 [newImage lockFocus
];
3491 newRect.origin
= newPoint
;
3492 newRect.size.width
= scaledWidth
;
3493 newRect.size.height
= scaledHeight
;
3495 //NSLog(@"newPoint: %@", NSStringFromRect(newRect));
3499 NSAffineTransform
*rotateTF
= [NSAffineTransform transform
];
3500 NSPoint centerPoint
= NSMakePoint(targetSize.width
/ 2, targetSize.height
/ 2);
3502 [rotateTF translateXBy
: centerPoint.x yBy
: centerPoint.y
];
3503 [rotateTF rotateByDegrees
: - 90];
3504 [rotateTF translateXBy
: -centerPoint.y yBy
: -centerPoint.x
];
3508 [mImage drawInRect
: newRect fromRect
: NSZeroRect operation
: NSCompositeSourceOver fraction
: 1.0];
3510 [newImage unlockFocus
];
3512 [[mLevelIndicator cell
] setImage
:newImage
];
3514 [newImage autorelease
];
3516 void SCLevelIndicator
::resetParams()
3519 [mLevelIndicator setUpWarning
:mWarning
* mNumSteps
];
3520 [mLevelIndicator setUpCritical
:mCritical
* mNumSteps
];
3521 [mLevelIndicator setMaxValue
: mNumSteps
];
3523 [mLevelIndicator setUpWarning
:mWarning
];
3524 [mLevelIndicator setUpCritical
:mCritical
];
3525 [mLevelIndicator setMaxValue
: 1.0];
3527 [mLevelIndicator setNeedsDisplay
:YES
];
3530 int SCLevelIndicator
::setProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
3533 char *name
= symbol
->name
;
3535 if (strcmp(name
, "value")==0) {
3537 err
= slotDoubleVal(slot
, &value
);
3538 if (err
) return err
;
3539 if(mStyle
>= 2) value
= value
* mNumSteps
;
3540 [mLevelIndicator setDoubleValue
:value
];
3544 if (strcmp(name
, "warning")==0) {
3546 err
= slotDoubleVal(slot
, &value
);
3547 if (err
) return err
;
3553 if (strcmp(name
, "critical")==0) {
3555 err
= slotDoubleVal(slot
, &value
);
3556 if (err
) return err
;
3562 if (strcmp(name
, "visible")==0) {
3563 bool visible
= IsTrue(slot
);
3565 setVisibleFromParent();
3569 if (strcmp(name
, "bounds")==0) {
3571 err
= slotGetSCRect(slot
, &screct
);
3572 if (err
) return err
;
3577 if (strcmp(name
, "enabled")==0) {
3578 bool enabled
= IsTrue(slot
);
3579 if (mEnabled
!= enabled
) {
3581 [mLevelIndicator setEnabled
:(BOOL)enabled
];
3582 if (!mEnabled
) mTop
->resetFocus();
3588 if (strcmp(name
, "style")==0) {
3590 err
= slotIntVal(slot
, &style
);
3591 if (err
) return err
;
3593 [[mLevelIndicator cell
] setLevelIndicatorStyle
:NSContinuousCapacityLevelIndicatorStyle
];
3595 } else if(style
== 1) {
3596 [[mLevelIndicator cell
] setLevelIndicatorStyle
:NSRelevancyLevelIndicatorStyle
];
3598 } else if(style
== 2) {
3599 [[mLevelIndicator cell
] setLevelIndicatorStyle
:NSDiscreteCapacityLevelIndicatorStyle
];
3602 [[mLevelIndicator cell
] setLevelIndicatorStyle
:NSRatingLevelIndicatorStyle
];
3610 if (strcmp(name
, "numSteps")==0) {
3612 err
= slotIntVal(slot
, &numSteps
);
3613 if (err
) return err
;
3614 mNumSteps
= numSteps
>= 1 ?
(double)numSteps
: 1.0;
3620 if (strcmp(name
, "numTicks")==0) {
3622 err
= slotIntVal(slot
, &numTicks
);
3623 if (err
) return err
;
3624 [mLevelIndicator setNumberOfTickMarks
:numTicks
];
3626 mTickHeight
= [mLevelIndicator rectOfTickMarkAtIndex
:0].size.height
; // 0 will be major if there are any
3629 [mLevelIndicator setPeakSubtract
:mTickHeight
];
3634 if (strcmp(name
, "numMajorTicks")==0) {
3636 err
= slotIntVal(slot
, &numTicks
);
3637 if (err
) return err
;
3638 [mLevelIndicator setNumberOfMajorTickMarks
:numTicks
];
3639 if([mLevelIndicator numberOfTickMarks
] > 0)
3640 mTickHeight
= [mLevelIndicator rectOfTickMarkAtIndex
:0].size.height
; // 0 will be major if there are any
3643 [mLevelIndicator setPeakSubtract
:mTickHeight
];
3648 if (strcmp(name
, "image")==0) {
3649 if(isKindOfSlot(slot
, s_scimage
->u.classobj
)) { // it's an SCImage : )
3650 SCImage
*scimage
= (SCImage
*)slotRawPtr(slotRawObject(slot
)->slots
);
3652 NSImage
*oldImage
= mImage
;
3653 mImage
= [[scimage nsimage
] retain
];
3659 post("Invalid Image");
3660 return errWrongType
;
3663 return errWrongType
;
3667 if (strcmp(name
, "drawsPeak")==0) {
3668 bool drawsPeak
= IsTrue(slot
);
3669 [mLevelIndicator setDrawPeak
:drawsPeak
];
3673 if (strcmp(name
, "peakLevel")==0) {
3675 err
= slotFloatVal(slot
, &value
);
3676 if (err
) return err
;
3677 [mLevelIndicator setPeakLevel
:sc_clip(value
, 0.f
, 1.f
)];
3681 return SCView
::setProperty(symbol
, slot
);
3685 int SCLevelIndicator
::getProperty(PyrSymbol
*symbol
, PyrSlot
*slot
)
3687 char *name
= symbol
->name
;
3689 if (strcmp(name
, "value")==0) {
3690 double value
= [mLevelIndicator doubleValue
];
3691 SetFloat(slot
, value
);
3695 return SCView
::getProperty(symbol
, slot
);
3699 void SCLevelIndicator
::setVisibleFromParent()
3701 if(mVisible
&& mParent
->isVisible()) {
3702 [mLevelIndicator setHidden
:NO
];
3704 [mLevelIndicator setHidden
:YES
];
3706 [mLevelIndicator setNeedsDisplay
:YES
];
3711 void SCLevelIndicator
::tabPrevFocus()
3713 mTop
->tabPrevFocus();
3715 void SCLevelIndicator
::tabNextFocus()
3717 //post("next focus\n");
3718 mTop
->tabNextFocus();