new files for 2.9
[TestXSLT.git] / MyDocument.m
1 //
2 //  MyDocument.m
3 //  TestXSLT
4 //
5 //  Created by Marc Liyanage on Sun Mar 03 2002.
6 //  Copyright (c) 2001 __MyCompanyName__. All rights reserved.
7 //
8 // $Id$
9
10 #import "MyDocument.h"
11 #import "Workset.h"
12
13
14
15
16 @implementation MyDocument
17
18 - (id)init {
19
20         if (self = [super init]) {
21                 workset = [[Workset alloc] init];
22                 processor = [XSLTProcessorFactory makeProcessorOfType:PROCESSORTYPE_SABLOTRON];
23                 wellFormedParser = [[XMLParserLibxml alloc] init];
24                 xmlDirty = NO;
25                 xsltDirty = NO;
26         }
27
28         
29         
30         return self;
31 }
32
33 - (void)dealloc {
34
35         [workset release];
36         [processor release];
37         [wellFormedParser release];
38         [findPanelController release];
39         [jumpToLinePanelController release];
40         [unsavedChangesPanelController release];
41
42 }
43
44 - (IBAction)selectTab:(id)sender {
45
46         [self selectTabById:[sender tag]];
47         
48 }
49
50
51
52
53
54
55 - (IBAction)selectTabById:(int)tabId {
56
57         NSString *tabName;
58
59         switch (tabId) {
60
61                 case XML:
62                         tabName = @"xmlTab";
63                         break;
64
65                 case XSLT:
66                         tabName = @"xsltTab";
67                         break;
68
69                 case PARAMETERS:
70                         tabName = @"parametersTab";
71                         break;
72
73                 case RESULT:
74                 default:
75                         tabName = @"resultTab";
76                         break;
77
78
79         }
80
81         [tabView selectTabViewItemWithIdentifier:tabName];
82
83 }
84
85 - (void)textViewDidChangeSelection:(NSNotification *)aNotification {
86         [self updateUI];
87 }
88
89
90 - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem {
91
92         [[self undoManager] removeAllActions];
93
94         [self doUpdateUI];
95 }
96
97
98
99
100 - (void)updateUI {
101         
102 //      NSLog(@"updateUI running...");
103
104         [uiUpdateTimer invalidate];
105         [uiUpdateTimer release];
106
107         uiUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(uiUpdateTimerTarget:) userInfo:nil repeats:NO];
108
109         [uiUpdateTimer retain];
110
111 }
112
113 - (void)uiUpdateTimerTarget:(NSTimer *)timer {
114
115         [self doUpdateUI];
116         [timer release];
117         uiUpdateTimer = nil;
118 }
119
120
121
122 - (void)doUpdateUI {
123
124         NSString *activeTabIdentifier = [[tabView selectedTabViewItem] identifier];
125         NSString *activeResultTabIdentifier = [[resultTabView selectedTabViewItem] identifier];
126
127         BOOL xmlTabIsVisible = [activeTabIdentifier isEqualToString:@"xmlTab"];
128         BOOL xsltTabIsVisible = !xmlTabIsVisible && [activeTabIdentifier isEqualToString:@"xsltTab"];
129         BOOL paramTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible) && [activeTabIdentifier isEqualToString:@"parametersTab"];
130         BOOL resultTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible || paramTabIsVisible);
131         BOOL resultTabHtmlIsVisible = resultTabIsVisible && [activeResultTabIdentifier isEqualToString:@"htmlResult"];
132         BOOL resultTabXslfoIsVisible = resultTabIsVisible && !resultTabHtmlIsVisible && [activeResultTabIdentifier isEqualToString:@"xslfoResult"];
133         BOOL resultTabTextIsVisible = resultTabIsVisible && !(resultTabHtmlIsVisible || resultTabXslfoIsVisible);
134         
135 //      NSLog(@"xml: %d, xslt: %d, param: %d, result: %d, reshtml: %d, resxslfo: %d, restext: %d", xmlTabIsVisible, xsltTabIsVisible, paramTabIsVisible, resultTabIsVisible, resultTabHtmlIsVisible, resultTabXslfoIsVisible, resultTabTextIsVisible);
136         
137         if (xmlTabIsVisible) {
138                 [saveXmlFilenameField setObjectValue:[workset xmlFilename]];
139                 [saveXmlFilenameField setToolTip:[workset xmlFilename]];
140                 [saveXmlButton setEnabled:[workset hasXmlFilename] && xmlDirty];
141                 [saveXmlAsButton setEnabled:[workset hasXmlCode]];
142                 [xmlTagStackField setStringValue:[xmlView calculateTagStack]];
143         
144                 [xmlView checkWellFormed];
145                 if ([workset hasXmlCode] && [xmlView hasError]) {
146                         [xmlWellFormedIcon setImage:warningIcon];
147                         [xmlWellFormedIcon setToolTip:[xmlView valueForKey:@"errorString"]];
148                 } else {
149                         [xmlWellFormedIcon setImage:nil];
150                         [xmlWellFormedIcon setToolTip:nil];
151                 }
152         
153         } else if (xsltTabIsVisible) {
154                 [saveXsltFilenameField setObjectValue:[workset xsltFilename]];
155                 [saveXsltFilenameField setToolTip:[workset xsltFilename]];
156                 [saveXsltButton setEnabled:[workset hasXsltFilename] && xsltDirty];
157                 [saveXsltAsButton setEnabled:[workset hasXsltCode]];
158                 [xsltTagStackField setStringValue:[xsltView calculateTagStack]];
159
160                 [xsltView checkWellFormed];
161                 if ([workset hasXsltCode] && [xsltView hasError]) {
162                         [xsltWellFormedIcon setImage:warningIcon];
163                         [xsltWellFormedIcon setToolTip:[xsltView valueForKey:@"errorString"]];
164                 } else {
165                         [xsltWellFormedIcon setImage:nil];
166                         [xsltWellFormedIcon setToolTip:nil];
167                 }
168
169         } else if (paramTabIsVisible) {
170                 [paramRemoveButton setEnabled:[parameterTable selectedRow] != -1];
171                 [parameterTable reloadData];
172         } else if (resultTabIsVisible) {
173                 [saveResultAsButton setEnabled:[workset hasResult]];
174                 [saveResultButton setEnabled:[workset hasResultFilename] && resultDirty];
175                 [autoSaveCheckbox setEnabled:[workset hasResultFilename]];
176                 [openResultURLButton setEnabled:[workset hasResultFilename]];
177                 [autoShowCheckbox setEnabled:[openResultURLButton isEnabled]];
178                 [saveResultFilenameField setObjectValue:[workset resultFilename]];
179                 [saveResultFilenameField setToolTip:[workset resultFilename]];
180
181                 if (resultTabHtmlIsVisible) {
182                         [self resizeWebView];
183                         [self updateResultWebView];
184                 } else if (resultTabXslfoIsVisible) {
185                         [self updateResultImageView];
186                         [pdfCurrentPageField setIntValue: (pdfPageCount ? (pdfCurrentPage + 1) : 0)];
187                         [pdfPageCountField setIntValue:pdfPageCount];
188                         
189                         [pdfPreviousPageButton setEnabled:pdfCurrentPage > 0];
190                         [pdfNextPageButton setEnabled:pdfCurrentPage < (pdfPageCount - 1)];
191                         [pdfSaveAsButton setEnabled:(pdfPageCount > 0)];
192 //              } else if (resultTabTextIsVisible) {
193                         
194                 }
195         }
196         
197
198         [processButton setEnabled:[self canProcessNow]];
199         
200         // move this to xmlview.
201 //      [self updateWellFormedIcons];
202         
203
204         
205         [resultView setString:[workset stringResult]];
206         
207 }
208
209
210 - (void)updateResultWebView {
211         if (!webViewUpToDate) {
212                 WebFrame *mainFrame = [resultWebView mainFrame];
213                 [mainFrame loadHTMLString:[workset stringResult] baseURL:nil];
214                 webViewUpToDate = YES;
215         }
216 }
217
218
219 - (void)updateResultImageView {
220         if (!imageViewUpToDate) {
221                 [self renderFo:self];
222                 imageViewUpToDate = YES;
223         }
224 }
225
226
227
228 - (BOOL)canProcessNow {
229
230         return [workset hasXmlCode] && [workset hasXsltCode];
231
232 }
233
234 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
235
236 //      NSLog(@"validate: %@, tag: %d", menuItem, [menuItem tag]);
237
238         switch ([menuItem tag]) {
239
240                 case 10:        // Process
241                         return [self canProcessNow];
242                         break;
243
244                 case 11:        // Save
245                         return [workset hasResultFilename];
246                         break;
247
248                 case 12:        // Find
249                         return [self canFindNow];
250                         break;
251
252                 case 13:        // Find Next
253                 case 14:        // Find Previous
254                         return [self canFindAgainNow];
255                         break;
256
257                 case 15:        // Use Selection for Find
258                         return [self canUseSelectionForFindNow];
259                         break;
260
261                 case 16:        // Jump to Line
262                         return [self canJumpToLineNow];
263                         break;
264                         
265                         
266                 default:
267                         return YES;
268                         break;
269
270         }
271
272
273 }
274
275 - (IBAction)showInBrowser:(id)sender {
276
277         
278
279 }
280
281
282 - (void)updateCompleteUI {
283
284         [xmlView setString:[workset xmlCode]];
285         [xsltView setString:[workset xsltCode]];
286         [self doUpdateUI];
287         
288 }
289
290 - (void)textDidChange:(NSNotification *)aNotification {
291
292         id sender = [aNotification object];
293
294         if ([sender isEqual:xmlView]) {
295                 [workset setXmlCode:[xmlView string]];
296                 xmlDirty = YES;
297         } else if ([sender isEqual:xsltView]) {
298                 [workset setXsltCode:[xsltView string]];
299                 xsltDirty = YES;
300         }
301
302         [self updateChangeCount:NSChangeDone];
303         [self updateUI];
304         
305 }
306
307
308
309 - (NSTabView *)tabView {
310
311         return tabView;
312
313 }
314
315 - (BOOL)canJumpToLineNow {
316
317         NSTextView *view = [self currentTextView];
318
319         return (view == xmlView) || (view == xsltView);
320         
321 }
322
323
324 - (IBAction)showJumpToLinePanel:(id)sender {
325
326         [NSApp beginSheet:[jumpToLinePanelController window]
327        modalForWindow:[[[self windowControllers] objectAtIndex:0] window]
328         modalDelegate:nil
329        didEndSelector:nil
330           contextInfo:nil];
331
332     [NSApp runModalForWindow:[jumpToLinePanelController window]];
333     [NSApp endSheet:[jumpToLinePanelController window]];
334     [[jumpToLinePanelController window] orderOut:self];
335
336         if ([jumpToLinePanelController lineNumber] == 0) {
337                 return;
338         }
339
340         [((XMLTextView *)[self currentTextView]) selectLineByNumber:[jumpToLinePanelController lineNumber]];
341
342 //      NSLog(@"jump to line: %d", [jumpToLinePanelController lineNumber]);
343
344 }
345
346
347 - (IBAction)showFindPanel:(id)sender {
348
349         [findPanelController refresh];
350
351         [NSApp beginSheet:[findPanelController window]
352        modalForWindow:[[[self windowControllers] objectAtIndex:0] window]
353         modalDelegate:nil
354        didEndSelector:nil
355           contextInfo:nil];
356         
357     [NSApp runModalForWindow:[findPanelController window]];
358     [NSApp endSheet:[findPanelController window]];
359     [[findPanelController window] orderOut:self];
360
361         if ([findPanelController aborted]) {
362                 return;
363         }
364
365         [self findStringWithSearchFlags:[findPanelController searchFlags]];
366         
367 }
368
369
370
371
372 - (IBAction)findNext:(id)sender {
373
374         [self findStringWithSearchFlags:[findPanelController searchFlags] & NSCaseInsensitiveSearch];
375
376 }
377
378
379 - (IBAction)findPrevious:(id)sender {
380
381         [self findStringWithSearchFlags:([findPanelController searchFlags] | NSBackwardsSearch)];
382
383 }
384
385 - (BOOL)canUseSelectionForFindNow {
386
387         NSTextView *view = [self currentTextView];
388         NSRange selectedRange;
389
390         if (view == nil) {
391                 return NO;
392         }
393
394         selectedRange = [view selectedRange];
395
396         if (selectedRange.length < 1) {
397                 return NO;
398         }
399
400         return YES;
401         
402 }
403
404
405
406 - (IBAction)useSelectionForFind:(id)sender {
407
408         NSString *text;
409         NSTextView *view = [self currentTextView];
410         
411         text = [[view string] substringWithRange:[view selectedRange]];
412
413         [findPanelController setFindString:text];
414         
415 }
416
417
418
419
420 - (BOOL)canFindNow {
421
422         NSString *currentTabViewItem = [[[self tabView] selectedTabViewItem] identifier];
423         
424         if ([currentTabViewItem isEqualToString:@"xmlTab"]
425             || [currentTabViewItem isEqualToString:@"xsltTab"]
426             || [currentTabViewItem isEqualToString:@"resultTab"]) {
427                 return YES;
428         }
429
430         return NO;
431         
432 }
433
434 - (BOOL)canFindAgainNow {
435
436         return ([findPanelController findString] != nil) && [self canFindNow];
437
438 }
439
440
441 - (void)findStringWithSearchFlags:(int)flags {
442
443         NSTextView *currentView;
444         NSString *text;
445         NSString *string;
446         NSRange selectedRange, leftRange, rightRange, resultRange, searchRange;
447
448         NSPasteboard *findBoard = [NSPasteboard pasteboardWithName:NSFindPboard];
449         [findBoard types];
450         string = [findBoard stringForType:NSStringPboardType];
451
452         currentView = [self currentTextView];
453         if (currentView == nil) {
454                 return;
455         }
456
457         text = [currentView string];
458         
459         selectedRange = [currentView selectedRange];
460         leftRange = NSMakeRange(0, selectedRange.location);
461         rightRange = NSMakeRange(NSMaxRange(selectedRange), [text length] - NSMaxRange(selectedRange));
462         
463         if (flags & NSBackwardsSearch) {
464                 searchRange = leftRange;
465         } else {
466                 searchRange = rightRange;
467         }
468         
469         resultRange = [text rangeOfString:string options:flags range:searchRange];
470
471         if (resultRange.location == NSNotFound) {
472                 NSBeep();
473                 return;
474         }
475
476         [currentView setSelectedRange:resultRange];
477         [currentView scrollRangeToVisible:resultRange];
478
479 }
480
481
482
483
484 - (NSTextView *)currentTextView {
485
486         NSString *currentTabViewItem = [[[self tabView] selectedTabViewItem] identifier];
487
488         if ([currentTabViewItem isEqualToString:@"xmlTab"]) {
489                 return xmlView;
490         } else if ([currentTabViewItem isEqualToString:@"xsltTab"]) {
491                 return xsltView;
492         } else if ([currentTabViewItem isEqualToString:@"resultTab"]) {
493                 return resultView;
494         }
495
496         return nil;
497
498 }
499
500
501
502
503
504 - (IBAction)process:(id)sender {
505
506         
507         const char **params = [[workset parameterSet] cArray];
508         
509         struct timeval tstart, tend;
510         gettimeofday(&tstart, NULL);
511         
512         long processingTime;
513
514         if ([workset hasXsltFilename]) {
515                 [processor setBaseUri:[NSString stringWithFormat:@"file://%@", [workset xsltFilename]]];
516         }
517
518         if (![processor processStrings:[XMLUtils getDataWithEncodingFromString:[workset xmlCode]] withXslt:[XMLUtils getDataWithEncodingFromString:[workset xsltCode]] andParameters:params]) {
519
520                 [drawerMessageField setStringValue:[NSString stringWithFormat:@"Error on line %d of your %@ code:\n%@", [processor errorLine], ([processor errorSource] == XSLT_ERROR_SOURCE_XML ? @"XML" : @"XSLT"), [processor errorMessage]]];
521
522                 NSBeep();
523                 [errorDrawer openOnEdge:NSMinYEdge];
524                 [self showErrorLocation:nil];
525
526         } else {
527
528                 gettimeofday(&tend, NULL);
529
530                 processingTime = ((tend.tv_sec * 1000000 + tend.tv_usec) - (tstart.tv_sec * 1000000 + tstart.tv_usec)) / 1000;
531                 
532                 [workset setResult:[processor result]];
533                 [workset setResultEncoding:[processor resultEncoding]];
534                 resultDirty = YES;
535                 [self autoSave];
536                 [errorDrawer close];
537                 [self selectTabById:RESULT];
538                 [processingTimeField setStringValue:[NSString stringWithFormat:@"Time: %ldms", processingTime]];
539         }
540
541         webViewUpToDate = NO;
542         imageViewUpToDate = NO;
543         
544         [self updateUI];
545 }
546
547
548 - (void)autoSave {
549
550         if (resultDirty && [autoSaveCheckbox state] == NSOnState) {
551                 [self saveResult:nil];
552         }
553
554 }
555
556 - (void)autoShow {
557
558         if ([autoShowCheckbox state] == NSOnState) {
559                 [self openResultURL:nil];
560         }
561
562 }
563
564
565 - (IBAction)loadXml:(id)sender {
566
567         NSOpenPanel *panel = [NSOpenPanel openPanel];
568
569         if ([panel runModalForDirectory:nil file:nil types:nil] == NSOKButton) {
570
571                 //      NSLog(@"choosen: %@", [[panel filenames] objectAtIndex:0]);
572
573                 [workset setXmlCode:[XMLUtils getStringWithEncodingFromFile:[[panel filenames] objectAtIndex:0]]];
574                 [workset setXmlFilename:[[panel filenames] objectAtIndex:0]];
575                 [self updateChangeCount:NSChangeDone];
576                 [self updateCompleteUI];
577         }
578 }
579
580
581
582
583
584 - (IBAction)loadXslt:(id)sender {
585
586         NSOpenPanel *panel = [NSOpenPanel openPanel];
587
588         if ([panel runModalForDirectory:nil file:nil types:nil] == NSOKButton) {
589
590                 //      NSLog(@"choosen: %@", [[panel filenames] objectAtIndex:0]);
591
592                 [workset setXsltCode:[XMLUtils getStringWithEncodingFromFile:[[panel filenames] objectAtIndex:0]]];
593                 [workset setXsltFilename:[[panel filenames] objectAtIndex:0]];
594                 [self updateChangeCount:NSChangeDone];
595                 [self updateCompleteUI];
596
597         }
598 }
599
600
601
602 - (IBAction)saveXmlAs:(id)sender {
603
604         NSSavePanel *panel = [NSSavePanel savePanel];
605
606         if ([panel runModal] == NSFileHandlingPanelOKButton) {
607
608                 [workset setXmlFilename:[panel filename]];
609                 [self saveXml:nil];
610
611         }
612 }
613
614
615
616 - (IBAction)saveXml:(id)sender {
617
618
619         if ([workset hasXmlFilename]) {
620                 [workset saveXml];
621                 xmlDirty = NO;
622         }
623
624         [self updateUI];
625 }
626
627
628 - (IBAction)saveXsltAs:(id)sender {
629
630         NSSavePanel *panel = [NSSavePanel savePanel];
631
632         if ([panel runModal] == NSFileHandlingPanelOKButton) {
633
634                 [workset setXsltFilename:[panel filename]];
635                 [self saveXslt:nil];
636
637         }
638 }
639
640
641
642 - (IBAction)saveXslt:(id)sender {
643
644         if ([workset hasXsltFilename]) {
645                 [workset saveXslt];
646                 xsltDirty = NO;
647         }
648
649         [self updateUI];
650 }
651
652
653
654 - (IBAction)saveResultAs:(id)sender {
655
656         NSSavePanel *panel = [NSSavePanel savePanel];
657
658         if ([panel runModal] == NSFileHandlingPanelOKButton) {
659
660                 [workset setResultFilename:[panel filename]];
661
662                 [self saveResult:nil];
663                 
664         }
665 }
666
667 - (IBAction)saveResult:(id)sender {
668
669         if ([workset hasResultFilename]) {
670
671                 [[workset result] writeToFile:[workset resultFilename] atomically:NO];
672                 resultDirty = NO;
673
674         }
675
676         [self updateUI];
677         [self autoShow];
678         
679 }
680
681
682 - (IBAction)openResultURL:(id)sender {
683
684 //      NSLog(@"openResultURL running...");
685         
686         if ([workset hasResultFilename]) {
687
688                 [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:[workset resultFilename]]];
689
690         }
691 }
692
693
694 - (IBAction)newParameter:(id)sender {
695
696         [[workset parameterSet] addParameter:@"name" withValue:@"value"];
697         [self doUpdateUI];
698         
699 }
700
701 - (IBAction)removeParameter:(id)sender {
702
703         int row = [parameterTable selectedRow];
704
705         if (row != -1) {
706                 [[workset parameterSet] removeParameterAtIndex:row];
707                 [self doUpdateUI];
708         } else {
709                 NSBeep();
710         }
711
712 }
713
714 - (int)numberOfRowsInTableView:(NSTableView *)aTableView {
715         return [[workset parameterSet] count];
716 }
717
718 - (id)tableView:(NSTableView *)aTableView
719 objectValueForTableColumn:(NSTableColumn *)aTableColumn
720                                          row:(int)rowIndex {
721
722         return [[workset parameterSet] getField:[aTableColumn identifier] atIndex:rowIndex];
723 }
724
725
726
727 - (void)tableView:(NSTableView *)aTableView
728    setObjectValue:(id)anObject
729    forTableColumn:(NSTableColumn *)aTableColumn
730                           row:(int)rowIndex {
731
732         [[workset parameterSet] setField:[aTableColumn identifier] atIndex:rowIndex toString:anObject];
733 }
734
735
736
737
738 - (IBAction)setProcessorType:(id)sender {
739
740         int newType = [sender tag];
741
742         if ([processor processorType] == newType) {
743                 return;
744         }
745
746         [self switchProcessorToType:newType updateUI:NO];
747
748 }
749
750
751 - (IBAction)switchProcessorToType:(int)newType updateUI:(BOOL)updateUI {
752
753         XSLTProcessor *newProcessor = nil;
754
755         newProcessor = [XSLTProcessorFactory makeProcessorOfType:newType];
756
757         if (!newProcessor) {
758                 NSLog(@"Unable to create new processor of type '%d'", newType);
759         }
760
761         [processor release];
762         processor = newProcessor;
763
764         if (updateUI) {
765                 [processorTypePopUp selectItemAtIndex:[processorTypePopUp indexOfItemWithTag:newType]];
766         }
767
768
769 }
770
771
772
773 - (id)handleProcessScriptCommand:(NSScriptCommand *)command {
774
775         if ([self canProcessNow]) {
776                 [self process:nil];
777         }
778
779         return nil;
780         
781 }
782
783
784 - (id)handleExportScriptCommand:(NSScriptCommand *)command {
785
786         NSDictionary *args = [command evaluatedArguments];
787     NSString *file = [args objectForKey:@"File"];
788
789 //      NSLog(file);
790
791         if (file != nil) {
792
793                 [workset setResultFilename:file];
794
795                 [self saveResult:nil];
796         }
797
798         return nil;
799         
800 }
801
802 - (id)handleSetParamScriptCommand:(NSScriptCommand *)command {
803
804         NSDictionary *args = [command evaluatedArguments];
805     NSString *paramName = [args objectForKey:@"Name"];
806     NSString *paramValue = [args objectForKey:@"Value"];
807
808         [[workset parameterSet] removeParameterByName:paramName];
809         
810         [[workset parameterSet] addParameter:paramName withValue:paramValue];
811         [self doUpdateUI];
812
813         return nil;
814         
815 }
816
817 - (id)handleClearParamScriptCommand:(NSScriptCommand *)command {
818
819         NSDictionary *args = [command evaluatedArguments];
820     NSString *paramName = [args objectForKey:@"Name"];
821
822         [[workset parameterSet] removeParameterByName:paramName];
823         return nil;
824         
825 }
826
827 - (id)handleSetProcessorTypeScriptCommand:(NSScriptCommand *)command {
828
829         NSDictionary *args = [command evaluatedArguments];
830     NSString *processorType = [args objectForKey:@"Name"];
831         
832         if ([processorType caseInsensitiveCompare:@"libxslt"] == NSOrderedSame) {
833
834                 [self switchProcessorToType:PROCESSORTYPE_LIBXSLT updateUI:YES];
835
836         } else if ([processorType caseInsensitiveCompare:@"sablotron"] == NSOrderedSame) {
837
838                 [self switchProcessorToType:PROCESSORTYPE_SABLOTRON updateUI:YES];
839
840         } else if ([processorType caseInsensitiveCompare:@"saxon"] == NSOrderedSame) {
841
842                 [self switchProcessorToType:PROCESSORTYPE_SAXON updateUI:YES];
843
844         } else if ([processorType caseInsensitiveCompare:@"xalan-j"] == NSOrderedSame) {
845                 
846                 [self switchProcessorToType:PROCESSORTYPE_XALAN_J updateUI:YES];
847                 
848         } else {
849                 NSLog(@"unknown processor");
850         }
851
852         [self doUpdateUI];
853         return nil;
854
855 }
856
857 - (BOOL)handleDroppedFile:(NSString *)filename forTextView:(NSTextView *)sender {
858
859         NSString *fileContents = [XMLUtils getStringWithEncodingFromFile:filename];
860
861         if ([sender isEqual: xmlView]) {
862
863                 [self setXmlcode:fileContents];
864                 [workset setXmlFilename:filename];
865                 
866         } else if ([sender isEqual:xsltView]) {
867
868                 [self setXsltcode:fileContents];
869                 [workset setXsltFilename:filename];
870                 
871         } else {
872
873                 NSLog(@"Unknown sender view");
874
875         }
876
877         [self updateUI];
878         return YES;
879         
880 }
881
882
883
884
885 - (NSString *)xmlcode {
886         return [workset xmlCode];
887 }
888
889 - (void)setXmlcode:(NSString *)s {
890
891         NSString *currentContents = [[[NSString alloc] initWithString:[self xmlcode]] autorelease];
892
893         [[self undoManager] registerUndoWithTarget:self
894                                                                    selector:@selector(setXmlcode:)
895                                                                          object:currentContents];
896
897         [workset setXmlCode:s];
898         [self updateCompleteUI];
899 }
900
901
902
903 - (NSString *)xsltcode {
904         return [workset xsltCode];
905 }
906
907 - (void)setXsltcode:(NSString *)s {
908
909         NSString *currentContents = [[[NSString alloc] initWithString:[self xsltcode]] autorelease];
910
911         [[self undoManager] registerUndoWithTarget:self
912                                                                           selector:@selector(setXsltcode:)
913                                                                             object:currentContents];
914
915         [workset setXsltCode:s];
916         [self updateCompleteUI];
917 }
918
919
920 - (NSString *)result {
921         return [workset stringResult];
922 }
923
924
925
926 - (void)tableViewSelectionDidChange:(NSNotification *)notification {
927         [self doUpdateUI];
928 }
929
930
931 - (void)checkForExternalModifications {
932
933         BOOL keep = NO;
934         
935         if ([workset xmlModifiedExternally] && xmlDirty || [workset xsltModifiedExternally] && xsltDirty) {
936
937                 /* external changes conflicting with local changes detected.
938                  * Ask the user if we should keep the local unsaved changes
939                  */
940                 keep = [self showUnsavedChangesPanel];
941
942         }
943
944         if ([workset xmlModifiedExternally] && !(xmlDirty && keep)) {
945                         [workset reloadXmlFromFile];
946                         [self updateChangeCount:NSChangeDone];
947                         [self updateCompleteUI];
948                         xmlDirty = NO;
949         }
950
951         if ([workset xsltModifiedExternally] && !(xsltDirty && keep)) {
952                         [workset reloadXsltFromFile];
953                         [self updateChangeCount:NSChangeDone];
954                         [self updateCompleteUI];
955                         xsltDirty = NO;
956         }
957
958         [self updateUI];
959         
960 }
961
962
963 - (BOOL)showUnsavedChangesPanel {
964
965         [NSApp beginSheet:[unsavedChangesPanelController window]
966         modalForWindow:[[[self windowControllers] objectAtIndex:0] window]
967          modalDelegate:nil
968         didEndSelector:nil
969            contextInfo:nil];
970
971     [NSApp runModalForWindow:[unsavedChangesPanelController window]];
972     [NSApp endSheet:[unsavedChangesPanelController window]];
973     [[unsavedChangesPanelController window] orderOut:self];
974
975         return ([unsavedChangesPanelController keepChanges]);
976
977 }
978
979 - (IBAction)renderFo:(id)sender {
980
981         XSL_FO_Renderer *xfr = [[XSL_FO_Renderer alloc] init];
982
983         NSData *resultData = [xfr render:[workset result]];
984
985         [resultData retain];
986         [pdfData release];
987         pdfData = resultData;
988         
989         NSImage *pdfImage = [[[NSImage alloc] initWithData:resultData] autorelease];
990         [pdfImage setBackgroundColor:[NSColor whiteColor]];
991         [pdfImage setCacheMode:NSImageCacheNever];
992         
993         [resultImageView setImage:pdfImage];
994         [resultImageView setFrameSize:[pdfImage size]];
995
996         //:[[[pdfImage representations] objectAtIndex:0] bounds]
997         //[resultImageView sizeToFit];
998         
999         //[resultImageView setNeedsDisplay:YES];
1000
1001         //NSLog(@"image reps: -%@-", [pdfImage representations]);
1002         //NSLog(@"count: -%d-", [[[pdfImage representations] objectAtIndex:0] pageCount]);
1003         
1004         pdfPageCount = [[[pdfImage representations] objectAtIndex:0] pageCount];
1005         pdfCurrentPage = 0;
1006                 
1007         [xfr release];
1008         
1009 }
1010
1011
1012 - (IBAction)pdfPreviousPage:(id)sender {
1013         
1014         if (pdfCurrentPage > 0) {
1015                 pdfCurrentPage--;
1016                 [[[[resultImageView image] representations] objectAtIndex:0] setCurrentPage:pdfCurrentPage];
1017                 [resultImageView setNeedsDisplay:YES];
1018                 [self doUpdateUI];
1019         }
1020         
1021 }
1022
1023 - (IBAction)pdfNextPage:(id)sender {
1024         
1025         if (pdfCurrentPage < (pdfPageCount - 1)) {
1026                 pdfCurrentPage++;
1027                 [[[[resultImageView image] representations] objectAtIndex:0] setCurrentPage:pdfCurrentPage];
1028                 [resultImageView setNeedsDisplay:YES];
1029                 [self doUpdateUI];
1030         }
1031         
1032 }
1033
1034
1035 - (IBAction)pdfSaveAs:(id)sender {
1036
1037         NSSavePanel *panel = [NSSavePanel savePanel];
1038         
1039         if ([panel runModal] == NSFileHandlingPanelOKButton) {
1040                 
1041                 [pdfData writeToFile:[panel filename] atomically:YES];
1042
1043         }
1044         
1045 }
1046
1047
1048
1049
1050 - (void)windowDidBecomeMain:(NSNotification *)aNotification {
1051
1052         [self checkForExternalModifications];
1053
1054 }
1055
1056 - (void)windowDidResize:(NSNotification *)aNotification {
1057
1058         [self resizeWebView];
1059         
1060 }
1061
1062 - (void)resizeWebView {
1063         
1064         [[[resultWebView mainFrame] frameView] setFrame:[resultWebView frame]];
1065         [resultWebView setNeedsDisplay:YES];
1066
1067 }
1068
1069
1070
1071
1072
1073 - (NSString *)windowNibName
1074 {
1075     // Override returning the nib file name of the document
1076     // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
1077     return @"MyDocument";
1078 }
1079
1080 - (void)windowControllerDidLoadNib:(NSWindowController *) aController
1081 {
1082
1083         
1084                 
1085         NSSize errorDrawerSize;
1086
1087         [super windowControllerDidLoadNib:aController];
1088                 
1089         [resultImageView setImageAlignment:NSImageAlignTopLeft];
1090         //      [resultImageView setImageFrameStyle:NSImageFrameGroove];
1091         [resultImageView setImageScaling:NSScaleNone];
1092         [resultImageView setEditable:NO];
1093                 
1094         
1095         
1096         [resultWebView setTextSizeMultiplier:0.9];
1097         
1098         warningIcon = [xmlWellFormedIcon image];
1099         
1100         [self updateCompleteUI];
1101         
1102         errorDrawerSize = [errorDrawer contentSize];
1103         errorDrawerSize.height = 130;
1104         [errorDrawer setContentSize:errorDrawerSize];
1105         
1106
1107         
1108         
1109         if (findPanelController == nil) {
1110                 findPanelController = [[FindPanelController alloc] initWithWindowNibName:@"FindPanel"];
1111 //              NSLog(@"init find panel controller: %@", findPanelController);
1112         }
1113
1114         if (jumpToLinePanelController == nil) {
1115                 jumpToLinePanelController = [[JumpToLinePanelController alloc] initWithWindowNibName:@"JumpToLine"];
1116 //              NSLog(@"init jump to line panel controller: %@", jumpToLinePanelController);
1117         }
1118
1119         if (unsavedChangesPanelController == nil) {
1120                 unsavedChangesPanelController = [[UnsavedChangesPanelController alloc] initWithWindowNibName:@"UnsavedChanges"];
1121 //              NSLog(@"init unsaved changes panel controller: %@", unsavedChangesPanelController);
1122         }
1123
1124         
1125
1126         
1127 }
1128
1129
1130 - (IBAction)showErrorLocation:(id)sender {
1131
1132         XMLTextView *textView;
1133         int errorLine = 0;
1134
1135         if ([processor errorSource] == XSLT_ERROR_SOURCE_XML) {
1136                 [self selectTabById:XML];
1137                 textView = xmlView;
1138         } else {
1139                 [self selectTabById:XSLT];
1140                 textView = xsltView;
1141         }
1142
1143         errorLine = [processor errorLine];
1144
1145         [textView selectLineByNumber:errorLine];
1146 }
1147
1148
1149 - (NSData *)dataRepresentationOfType:(NSString *)aType
1150 {
1151     // Insert code here to write your document from the given data.  You can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.
1152         return [NSArchiver archivedDataWithRootObject:workset];
1153 }
1154
1155 - (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType
1156 {
1157     // Insert code here to read your document from the given data.  You can also choose to override -loadFileWrapperRepresentation:ofType: or -readFromFile:ofType: instead.
1158
1159         [workset release];
1160         workset = [[NSUnarchiver unarchiveObjectWithData:data] retain];
1161         [self updateCompleteUI];
1162
1163         return YES;
1164 }
1165
1166 @end