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