5 // Created by Marc Liyanage on Sun Mar 03 2002.
6 // Copyright (c) 2001 __MyCompanyName__. All rights reserved.
10 #import "MyDocument.h"
12 #import <Foundation/NSDebug.h>
16 @implementation MyDocument
20 // NSZombieEnabled = YES;
22 if (self = [super init]) {
23 workset = [[Workset alloc] init];
24 processor = [XSLTProcessorFactory makeProcessorOfType:PROCESSORTYPE_SABLOTRON];
25 wellFormedParser = [[XMLParserLibxml alloc] init];
30 defaults = [NSUserDefaults standardUserDefaults];
37 [uiUpdateTimer release];
40 [wellFormedParser release];
41 [findPanelController release];
42 [jumpToLinePanelController release];
43 [unsavedChangesPanelController release];
48 - (IBAction)selectTab:(id)sender {
50 [self selectTabById:[sender tag]];
55 - (IBAction)selectTabById:(int)tabId {
70 tabName = @"parametersTab";
75 tabName = @"resultTab";
80 [tabView selectTabViewItemWithIdentifier:tabName];
85 - (void)textViewDidChangeSelection:(NSNotification *)aNotification {
90 - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem {
92 [[self undoManager] removeAllActions];
100 // NSLog(@"updateUI running...");
102 [uiUpdateTimer invalidate];
103 [uiUpdateTimer release];
105 uiUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(uiUpdateTimerTarget:) userInfo:nil repeats:NO];
107 [uiUpdateTimer retain];
113 - (void)uiUpdateTimerTarget:(NSTimer *)timer {
123 NSString *activeTabIdentifier = [[tabView selectedTabViewItem] identifier];
124 NSString *activeResultTabIdentifier = [[resultTabView selectedTabViewItem] identifier];
126 BOOL xmlTabIsVisible = [activeTabIdentifier isEqualToString:@"xmlTab"];
127 BOOL xsltTabIsVisible = !xmlTabIsVisible && [activeTabIdentifier isEqualToString:@"xsltTab"];
128 BOOL paramTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible) && [activeTabIdentifier isEqualToString:@"parametersTab"];
129 BOOL resultTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible || paramTabIsVisible);
130 BOOL resultTabHtmlIsVisible = resultTabIsVisible && [activeResultTabIdentifier isEqualToString:@"htmlResult"];
131 BOOL resultTabXslfoIsVisible = resultTabIsVisible && !resultTabHtmlIsVisible && [activeResultTabIdentifier isEqualToString:@"xslfoResult"];
132 // BOOL resultTabTextIsVisible = resultTabIsVisible && !(resultTabHtmlIsVisible || resultTabXslfoIsVisible);
134 // NSLog(@"xml: %d, xslt: %d, param: %d, result: %d, reshtml: %d, resxslfo: %d, restext: %d", xmlTabIsVisible, xsltTabIsVisible, paramTabIsVisible, resultTabIsVisible, resultTabHtmlIsVisible, resultTabXslfoIsVisible, resultTabTextIsVisible);
136 if (xmlTabIsVisible) {
137 [saveXmlFilenameField setObjectValue:[workset xmlFilename]];
138 [saveXmlFilenameField setToolTip:[workset xmlFilename]];
139 [saveXmlButton setEnabled:[self canSaveXmlNow]];
140 [saveXmlAsButton setEnabled:[self canSaveXmlAsNow]];
141 [xmlTagStackField setStringValue:[xmlView calculateTagStack]];
143 if ([defaults boolForKey:@"enableWellformedCheck"]) {
144 [xmlView checkWellFormed];
145 if ([workset hasXmlCode] && [xmlView hasError]) {
146 [xmlWellFormedIcon setImage:warningIcon];
147 [xmlWellFormedIcon setToolTip:[xmlView valueForKey:@"errorString"]];
148 [self setValue:[xmlView valueForKey:@"errorString"] forKey:@"drawerMessage"];
150 [xmlWellFormedIcon setImage:nil];
151 [xmlWellFormedIcon setToolTip:nil];
152 [self setValue:nil forKey:@"drawerMessage"];
156 } else if (xsltTabIsVisible) {
157 [saveXsltFilenameField setObjectValue:[workset xsltFilename]];
158 [saveXsltFilenameField setToolTip:[workset xsltFilename]];
159 [saveXsltButton setEnabled:[self canSaveXsltNow]];
160 [saveXsltAsButton setEnabled:[self canSaveXsltAsNow]];
161 [xsltTagStackField setStringValue:[xsltView calculateTagStack]];
163 if ([defaults boolForKey:@"enableWellformedCheck"]) {
164 [xsltView checkWellFormed];
165 if ([workset hasXsltCode] && [xsltView hasError]) {
166 [xsltWellFormedIcon setImage:warningIcon];
167 [xsltWellFormedIcon setToolTip:[xsltView valueForKey:@"errorString"]];
168 [self setValue:[xsltView valueForKey:@"errorString"] forKey:@"drawerMessage"];
170 [xsltWellFormedIcon setImage:nil];
171 [xsltWellFormedIcon setToolTip:nil];
172 [self setValue:nil forKey:@"drawerMessage"];
176 } else if (paramTabIsVisible) {
177 [paramRemoveButton setEnabled:[parameterTable selectedRow] != -1];
178 [parameterTable reloadData];
179 } else if (resultTabIsVisible) {
180 [saveResultAsButton setEnabled:[self canSaveResultAsNow]];
181 [saveResultButton setEnabled:[self canSaveResultNow]];
182 [autoSaveCheckbox setEnabled:[workset hasResultFilename]];
183 [openResultURLButton setEnabled:[workset hasResultFilename]];
184 [autoShowCheckbox setEnabled:[openResultURLButton isEnabled]];
185 [saveResultFilenameField setObjectValue:[workset resultFilename]];
186 [saveResultFilenameField setToolTip:[workset resultFilename]];
188 if (resultTabHtmlIsVisible) {
189 [self resizeWebView];
190 [self updateResultWebView];
191 } else if (resultTabXslfoIsVisible) {
192 [self updateResultImageView];
193 [pdfCurrentPageField setIntValue: (pdfPageCount ? (pdfCurrentPage + 1) : 0)];
194 [pdfPageCountField setIntValue:pdfPageCount];
196 [pdfPreviousPageButton setEnabled:pdfCurrentPage > 0];
197 [pdfNextPageButton setEnabled:pdfCurrentPage < (pdfPageCount - 1)];
198 [pdfSaveAsButton setEnabled:(pdfPageCount > 0)];
199 // } else if (resultTabTextIsVisible) {
205 [processButton setEnabled:[self canProcessNow]];
207 // move this to xmlview.
208 // [self updateWellFormedIcons];
212 [resultView setString:[workset stringResult]];
217 - (void)updateResultWebView {
218 if (!webViewUpToDate) {
219 WebFrame *mainFrame = [resultWebView mainFrame];
220 // [mainFrame loadHTMLString:[workset stringResult] baseURL:nil];
221 [mainFrame loadHTMLString:[workset stringResult] baseURL:[NSURL URLWithString:[webViewBaseURL stringValue]]];
222 // [mainFrame loadHTMLString:[workset stringResult] baseURL:[NSURL URLWithString:@"file:///Users/liyanage/Sites/primavera/images/x"]];
223 webViewUpToDate = YES;
228 - (void)updateResultImageView {
229 if (!imageViewUpToDate) {
230 [self renderFo:self];
231 imageViewUpToDate = YES;
236 - (BOOL)canProcessNow {
238 return [workset hasXmlCode] && [workset hasXsltCode];
242 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
244 // NSLog(@"validate: %@, tag: %d", menuItem, [menuItem tag]);
246 NSString *activeTabIdentifier = [[tabView selectedTabViewItem] identifier];
247 BOOL xmlTabIsVisible = [activeTabIdentifier isEqualToString:@"xmlTab"];
248 BOOL xsltTabIsVisible = !xmlTabIsVisible && [activeTabIdentifier isEqualToString:@"xsltTab"];
249 BOOL paramTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible) && [activeTabIdentifier isEqualToString:@"parametersTab"];
250 BOOL resultTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible || paramTabIsVisible);
253 switch ([menuItem tag]) {
256 return [self canProcessNow];
260 return [workset hasResultFilename];
264 return [self canFindNow];
267 case 13: // Find Next
268 case 14: // Find Previous
269 return [self canFindAgainNow];
272 case 15: // Use Selection for Find
273 return [self canUseSelectionForFindNow];
276 case 16: // Jump to Line
277 return [self canJumpToLineNow];
280 case 17: // Save Current Pane
281 if (xmlTabIsVisible) {
282 return [self canSaveXmlNow];
283 } else if (xsltTabIsVisible) {
284 return [self canSaveXsltNow];
285 } else if (resultTabIsVisible) {
286 return [self canSaveResultNow];
290 case 18: // Save Current Pane As...
291 if (xmlTabIsVisible) {
292 return [self canSaveXmlAsNow];
293 } else if (xsltTabIsVisible) {
294 return [self canSaveXsltAsNow];
295 } else if (resultTabIsVisible) {
296 return [self canSaveResultAsNow];
306 return [super validateMenuItem:menuItem];
310 - (IBAction)showInBrowser:(id)sender {
317 - (void)updateCompleteUI {
319 [xmlView setString:[workset xmlCode]];
320 [xsltView setString:[workset xsltCode]];
325 - (void)textDidChange:(NSNotification *)aNotification {
327 id sender = [aNotification object];
329 if ([sender isEqual:xmlView]) {
330 [workset setXmlCode:[xmlView string]];
332 } else if ([sender isEqual:xsltView]) {
333 [workset setXsltCode:[xsltView string]];
337 [self updateChangeCount:NSChangeDone];
344 - (NSTabView *)tabView {
350 - (BOOL)canJumpToLineNow {
352 NSTextView *view = [self currentTextView];
354 return (view == xmlView) || (view == xsltView);
359 - (IBAction)showJumpToLinePanel:(id)sender {
361 [NSApp beginSheet:[jumpToLinePanelController window]
362 modalForWindow:[[[self windowControllers] objectAtIndex:0] window]
367 [NSApp runModalForWindow:[jumpToLinePanelController window]];
368 [NSApp endSheet:[jumpToLinePanelController window]];
369 [[jumpToLinePanelController window] orderOut:self];
371 if ([jumpToLinePanelController lineNumber] == 0) {
375 [((XMLTextView *)[self currentTextView]) selectLineByNumber:[jumpToLinePanelController lineNumber]];
377 // NSLog(@"jump to line: %d", [jumpToLinePanelController lineNumber]);
382 - (IBAction)showFindPanel:(id)sender {
384 [findPanelController refresh];
386 [NSApp beginSheet:[findPanelController window]
387 modalForWindow:[[[self windowControllers] objectAtIndex:0] window]
392 [NSApp runModalForWindow:[findPanelController window]];
393 [NSApp endSheet:[findPanelController window]];
394 [[findPanelController window] orderOut:self];
396 if ([findPanelController aborted]) {
400 [self findStringWithSearchFlags:[findPanelController searchFlags]];
407 - (IBAction)findNext:(id)sender {
409 [self findStringWithSearchFlags:[findPanelController searchFlags] & NSCaseInsensitiveSearch];
414 - (IBAction)findPrevious:(id)sender {
416 [self findStringWithSearchFlags:([findPanelController searchFlags] | NSBackwardsSearch)];
420 - (BOOL)canUseSelectionForFindNow {
422 NSTextView *view = [self currentTextView];
423 NSRange selectedRange;
429 selectedRange = [view selectedRange];
431 if (selectedRange.length < 1) {
441 - (IBAction)useSelectionForFind:(id)sender {
444 NSTextView *view = [self currentTextView];
446 text = [[view string] substringWithRange:[view selectedRange]];
448 [findPanelController setFindString:text];
457 NSString *currentTabViewItem = [[[self tabView] selectedTabViewItem] identifier];
459 if ([currentTabViewItem isEqualToString:@"xmlTab"]
460 || [currentTabViewItem isEqualToString:@"xsltTab"]
461 || [currentTabViewItem isEqualToString:@"resultTab"]) {
469 - (BOOL)canFindAgainNow {
471 return ([findPanelController findString] != nil) && [self canFindNow];
476 - (void)findStringWithSearchFlags:(int)flags {
478 NSTextView *currentView;
481 NSRange selectedRange, leftRange, rightRange, resultRange, searchRange;
483 NSPasteboard *findBoard = [NSPasteboard pasteboardWithName:NSFindPboard];
485 string = [findBoard stringForType:NSStringPboardType];
487 currentView = [self currentTextView];
488 if (currentView == nil) {
492 text = [currentView string];
494 selectedRange = [currentView selectedRange];
495 leftRange = NSMakeRange(0, selectedRange.location);
496 rightRange = NSMakeRange(NSMaxRange(selectedRange), [text length] - NSMaxRange(selectedRange));
498 if (flags & NSBackwardsSearch) {
499 searchRange = leftRange;
501 searchRange = rightRange;
504 resultRange = [text rangeOfString:string options:flags range:searchRange];
506 if (resultRange.location == NSNotFound) {
511 [currentView setSelectedRange:resultRange];
512 [currentView scrollRangeToVisible:resultRange];
519 - (NSTextView *)currentTextView {
521 NSString *currentTabViewItem = [[[self tabView] selectedTabViewItem] identifier];
523 if ([currentTabViewItem isEqualToString:@"xmlTab"]) {
525 } else if ([currentTabViewItem isEqualToString:@"xsltTab"]) {
527 } else if ([currentTabViewItem isEqualToString:@"resultTab"]) {
539 - (IBAction)process:(id)sender {
542 const char **params = [[workset parameterSet] cArray];
544 struct timeval tstart, tend;
545 gettimeofday(&tstart, NULL);
549 if ([workset hasXsltFilename]) {
550 [processor setBaseUri:[NSString stringWithFormat:@"file://%@", [workset xsltFilename]]];
553 if (![processor processStrings:[XMLUtils getDataWithEncodingFromString:[workset xmlCode]] withXslt:[XMLUtils getDataWithEncodingFromString:[workset xsltCode]] andParameters:params]) {
555 [self setValue:[NSString stringWithFormat:@"Error on line %d of your %@ code:\n%@", [processor errorLine], ([processor errorSource] == XSLT_ERROR_SOURCE_XML ? @"XML" : @"XSLT"), [processor errorMessage]] forKey:@"drawerMessage"];
558 [errorDrawer openOnEdge:NSMinYEdge];
559 [self showErrorLocation:nil];
563 gettimeofday(&tend, NULL);
565 processingTime = ((tend.tv_sec * 1000000 + tend.tv_usec) - (tstart.tv_sec * 1000000 + tstart.tv_usec)) / 1000;
567 [workset setResult:[processor result]];
568 [workset setResultEncoding:[processor resultEncoding]];
571 // [errorDrawer close];
572 [self selectTabById:RESULT];
573 [processingTimeField setStringValue:[NSString stringWithFormat:@"Time: %ldms", processingTime]];
576 webViewUpToDate = NO;
577 imageViewUpToDate = NO;
585 if (resultDirty && [autoSaveCheckbox state] == NSOnState) {
586 [self saveResult:nil];
593 if ([autoShowCheckbox state] == NSOnState) {
594 [self openResultURL:nil];
600 - (IBAction)loadXml:(id)sender {
602 NSOpenPanel *panel = [NSOpenPanel openPanel];
604 if ([panel runModalForDirectory:nil file:nil types:nil] == NSOKButton) {
606 // NSLog(@"choosen: %@", [[panel filenames] objectAtIndex:0]);
608 [workset setXmlCode:[XMLUtils getStringWithEncodingFromFile:[[panel filenames] objectAtIndex:0]]];
609 [workset setXmlFilename:[[panel filenames] objectAtIndex:0]];
610 [self updateChangeCount:NSChangeDone];
611 [self updateCompleteUI];
619 - (IBAction)loadXslt:(id)sender {
621 NSOpenPanel *panel = [NSOpenPanel openPanel];
623 if ([panel runModalForDirectory:nil file:nil types:nil] == NSOKButton) {
625 // NSLog(@"choosen: %@", [[panel filenames] objectAtIndex:0]);
627 [workset setXsltCode:[XMLUtils getStringWithEncodingFromFile:[[panel filenames] objectAtIndex:0]]];
628 [workset setXsltFilename:[[panel filenames] objectAtIndex:0]];
629 [self updateChangeCount:NSChangeDone];
630 [self updateCompleteUI];
638 - (BOOL)canSaveXmlAsNow {
639 return [workset hasXmlCode];
642 - (BOOL)canSaveXmlNow {
643 return [workset hasXmlFilename] && xmlDirty;
646 - (BOOL)canSaveXsltAsNow {
647 return [workset hasXsltCode];
650 - (BOOL)canSaveXsltNow {
651 return [workset hasXsltFilename] && xsltDirty;
654 - (BOOL)canSaveResultAsNow {
655 return [workset hasResult];
658 - (BOOL)canSaveResultNow {
659 return [workset hasResultFilename] && resultDirty;
665 - (IBAction)saveXmlAs:(id)sender {
667 NSSavePanel *panel = [NSSavePanel savePanel];
669 if ([panel runModal] == NSFileHandlingPanelOKButton) {
671 [workset setXmlFilename:[panel filename]];
679 - (IBAction)saveXml:(id)sender {
682 if ([workset hasXmlFilename]) {
691 - (IBAction)saveXsltAs:(id)sender {
693 NSSavePanel *panel = [NSSavePanel savePanel];
695 if ([panel runModal] == NSFileHandlingPanelOKButton) {
697 [workset setXsltFilename:[panel filename]];
705 - (IBAction)saveXslt:(id)sender {
707 if ([workset hasXsltFilename]) {
717 - (IBAction)saveResultAs:(id)sender {
719 NSSavePanel *panel = [NSSavePanel savePanel];
721 if ([panel runModal] == NSFileHandlingPanelOKButton) {
723 [workset setResultFilename:[panel filename]];
725 [self saveResult:nil];
730 - (IBAction)saveResult:(id)sender {
732 if ([workset hasResultFilename]) {
734 [[workset result] writeToFile:[workset resultFilename] atomically:NO];
745 - (IBAction)saveCurrentAs:(id)sender {
747 NSString *activeTabIdentifier = [[tabView selectedTabViewItem] identifier];
748 BOOL xmlTabIsVisible = [activeTabIdentifier isEqualToString:@"xmlTab"];
749 BOOL xsltTabIsVisible = !xmlTabIsVisible && [activeTabIdentifier isEqualToString:@"xsltTab"];
750 BOOL paramTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible) && [activeTabIdentifier isEqualToString:@"parametersTab"];
751 BOOL resultTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible || paramTabIsVisible);
753 if (xmlTabIsVisible) {
754 [self saveXmlAs:sender];
755 } else if (xsltTabIsVisible) {
756 [self saveXsltAs:sender];
757 } else if (resultTabIsVisible) {
758 [self saveResultAs:sender];
766 - (IBAction)saveCurrent:(id)sender {
768 NSString *activeTabIdentifier = [[tabView selectedTabViewItem] identifier];
769 BOOL xmlTabIsVisible = [activeTabIdentifier isEqualToString:@"xmlTab"];
770 BOOL xsltTabIsVisible = !xmlTabIsVisible && [activeTabIdentifier isEqualToString:@"xsltTab"];
771 BOOL paramTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible) && [activeTabIdentifier isEqualToString:@"parametersTab"];
772 BOOL resultTabIsVisible = !(xmlTabIsVisible || xsltTabIsVisible || paramTabIsVisible);
774 if (xmlTabIsVisible) {
775 [self saveXml:sender];
776 } else if (xsltTabIsVisible) {
777 [self saveXslt:sender];
778 } else if (resultTabIsVisible) {
779 [self saveResult:sender];
789 - (IBAction)openResultURL:(id)sender {
791 // NSLog(@"openResultURL running...");
793 if ([workset hasResultFilename]) {
795 [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:[workset resultFilename]]];
801 - (IBAction)newParameter:(id)sender {
803 [[workset parameterSet] addParameter:@"name" withValue:@"value"];
808 - (IBAction)removeParameter:(id)sender {
810 int row = [parameterTable selectedRow];
813 [[workset parameterSet] removeParameterAtIndex:row];
821 - (int)numberOfRowsInTableView:(NSTableView *)aTableView {
822 return [[workset parameterSet] count];
825 - (id)tableView:(NSTableView *)aTableView
826 objectValueForTableColumn:(NSTableColumn *)aTableColumn
829 return [[workset parameterSet] getField:[aTableColumn identifier] atIndex:rowIndex];
834 - (void)tableView:(NSTableView *)aTableView
835 setObjectValue:(id)anObject
836 forTableColumn:(NSTableColumn *)aTableColumn
839 [[workset parameterSet] setField:[aTableColumn identifier] atIndex:rowIndex toString:anObject];
845 - (IBAction)setProcessorType:(id)sender {
847 int newType = [sender tag];
849 if ([processor processorType] == newType) {
853 [self switchProcessorToType:newType updateUI:NO];
858 - (IBAction)switchProcessorToType:(int)newType updateUI:(BOOL)updateUI {
860 XSLTProcessor *newProcessor = nil;
862 newProcessor = [XSLTProcessorFactory makeProcessorOfType:newType];
865 NSLog(@"Unable to create new processor of type '%d'", newType);
869 processor = newProcessor;
872 [processorTypePopUp selectItemAtIndex:[processorTypePopUp indexOfItemWithTag:newType]];
880 - (id)handleProcessScriptCommand:(NSScriptCommand *)command {
882 if ([self canProcessNow]) {
891 - (id)handleExportScriptCommand:(NSScriptCommand *)command {
893 NSDictionary *args = [command evaluatedArguments];
894 NSString *file = [args objectForKey:@"File"];
900 [workset setResultFilename:file];
902 [self saveResult:nil];
909 - (id)handleSetParamScriptCommand:(NSScriptCommand *)command {
911 NSDictionary *args = [command evaluatedArguments];
912 NSString *paramName = [args objectForKey:@"Name"];
913 NSString *paramValue = [args objectForKey:@"Value"];
915 [[workset parameterSet] removeParameterByName:paramName];
917 [[workset parameterSet] addParameter:paramName withValue:paramValue];
924 - (id)handleClearParamScriptCommand:(NSScriptCommand *)command {
926 NSDictionary *args = [command evaluatedArguments];
927 NSString *paramName = [args objectForKey:@"Name"];
929 [[workset parameterSet] removeParameterByName:paramName];
934 - (id)handleSetProcessorTypeScriptCommand:(NSScriptCommand *)command {
936 NSDictionary *args = [command evaluatedArguments];
937 NSString *processorType = [args objectForKey:@"Name"];
939 if ([processorType caseInsensitiveCompare:@"libxslt"] == NSOrderedSame) {
941 [self switchProcessorToType:PROCESSORTYPE_LIBXSLT updateUI:YES];
943 } else if ([processorType caseInsensitiveCompare:@"sablotron"] == NSOrderedSame) {
945 [self switchProcessorToType:PROCESSORTYPE_SABLOTRON updateUI:YES];
947 } else if ([processorType caseInsensitiveCompare:@"saxon"] == NSOrderedSame) {
949 [self switchProcessorToType:PROCESSORTYPE_SAXON updateUI:YES];
951 } else if ([processorType caseInsensitiveCompare:@"xalan-j"] == NSOrderedSame) {
953 [self switchProcessorToType:PROCESSORTYPE_XALAN_J updateUI:YES];
956 NSLog(@"unknown processor");
964 - (BOOL)handleDroppedFile:(NSString *)filename forTextView:(NSTextView *)sender {
966 NSString *fileContents = [XMLUtils getStringWithEncodingFromFile:filename];
968 if ([sender isEqual: xmlView]) {
970 [self setXmlcode:fileContents];
971 [workset setXmlFilename:filename];
973 } else if ([sender isEqual:xsltView]) {
975 [self setXsltcode:fileContents];
976 [workset setXsltFilename:filename];
980 NSLog(@"Unknown sender view");
992 - (NSString *)xmlcode {
993 return [workset xmlCode];
996 - (void)setXmlcode:(NSString *)s {
998 NSString *currentContents = [[[NSString alloc] initWithString:[self xmlcode]] autorelease];
1000 [[self undoManager] registerUndoWithTarget:self
1001 selector:@selector(setXmlcode:)
1002 object:currentContents];
1004 [workset setXmlCode:s];
1005 [self updateCompleteUI];
1010 - (NSString *)xsltcode {
1011 return [workset xsltCode];
1014 - (void)setXsltcode:(NSString *)s {
1016 NSString *currentContents = [[[NSString alloc] initWithString:[self xsltcode]] autorelease];
1018 [[self undoManager] registerUndoWithTarget:self
1019 selector:@selector(setXsltcode:)
1020 object:currentContents];
1022 [workset setXsltCode:s];
1023 [self updateCompleteUI];
1027 - (NSString *)result {
1028 return [workset stringResult];
1033 - (void)tableViewSelectionDidChange:(NSNotification *)notification {
1038 - (void)checkForExternalModifications {
1042 if ([workset xmlModifiedExternally] && xmlDirty || [workset xsltModifiedExternally] && xsltDirty) {
1044 /* external changes conflicting with local changes detected.
1045 * Ask the user if we should keep the local unsaved changes
1047 keep = [self showUnsavedChangesPanel];
1051 if ([workset xmlModifiedExternally] && !(xmlDirty && keep)) {
1052 [workset reloadXmlFromFile];
1053 [self updateChangeCount:NSChangeDone];
1054 [self updateCompleteUI];
1058 if ([workset xsltModifiedExternally] && !(xsltDirty && keep)) {
1059 [workset reloadXsltFromFile];
1060 [self updateChangeCount:NSChangeDone];
1061 [self updateCompleteUI];
1070 - (BOOL)showUnsavedChangesPanel {
1072 [NSApp beginSheet:[unsavedChangesPanelController window]
1073 modalForWindow:[[[self windowControllers] objectAtIndex:0] window]
1078 [NSApp runModalForWindow:[unsavedChangesPanelController window]];
1079 [NSApp endSheet:[unsavedChangesPanelController window]];
1080 [[unsavedChangesPanelController window] orderOut:self];
1082 return ([unsavedChangesPanelController keepChanges]);
1086 - (void)xslfoRenderThread {
1088 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1090 XSL_FO_Renderer *xfr = [[[XSL_FO_Renderer alloc] init] autorelease];
1091 xslfoRendererResultData = [xfr render:[workset result]];
1094 [xslfoRendererLock unlockWithCondition:2];
1099 - (IBAction)renderFo:(id)sender {
1101 xslfoRendererLock = [[[NSConditionLock alloc] initWithCondition:1] autorelease];
1102 [NSThread detachNewThreadSelector:@selector(xslfoRenderThread) toTarget:self withObject:nil];
1103 [xslfoRendererLock lockWhenCondition:2];
1104 [xslfoRendererLock unlock];
1106 if (!xslfoRendererResultData) {
1107 NSLog(@"Unable to render, NULL result");
1111 [xslfoRendererResultData retain];
1113 pdfData = xslfoRendererResultData;
1115 NSImage *pdfImage = [[[NSImage alloc] initWithData:xslfoRendererResultData] autorelease];
1116 [pdfImage setBackgroundColor:[NSColor whiteColor]];
1118 [pdfImage setCacheMode:NSImageCacheNever];
1120 NSClipView *clipView = (NSClipView *)[resultImageView superview];
1121 NSScrollView *scrollView = (NSScrollView *)[clipView superview];
1123 [resultImageView setImage:pdfImage];
1124 [resultImageView setFrameSize:[pdfImage size]];
1125 [resultImageView display];
1127 [clipView scrollToPoint:NSMakePoint([resultImageView frame].origin.x, [resultImageView frame].size.height - [clipView frame].size.height + [resultImageView frame].origin.y)];
1128 [scrollView reflectScrolledClipView:clipView];
1130 pdfPageCount = [[[pdfImage representations] objectAtIndex:0] pageCount];
1136 - (IBAction)pdfPreviousPage:(id)sender {
1138 if (pdfCurrentPage > 0) {
1140 [[[[resultImageView image] representations] objectAtIndex:0] setCurrentPage:pdfCurrentPage];
1141 [resultImageView setNeedsDisplay:YES];
1147 - (IBAction)pdfNextPage:(id)sender {
1149 if (pdfCurrentPage < (pdfPageCount - 1)) {
1151 [[[[resultImageView image] representations] objectAtIndex:0] setCurrentPage:pdfCurrentPage];
1152 [resultImageView setNeedsDisplay:YES];
1159 - (IBAction)pdfSaveAs:(id)sender {
1161 NSSavePanel *panel = [NSSavePanel savePanel];
1163 if ([panel runModal] == NSFileHandlingPanelOKButton) {
1165 [pdfData writeToFile:[panel filename] atomically:YES];
1174 - (void)windowDidBecomeMain:(NSNotification *)aNotification {
1176 [self checkForExternalModifications];
1180 - (void)windowDidResize:(NSNotification *)aNotification {
1182 [self resizeWebView];
1186 - (void)resizeWebView {
1188 // [[[resultWebView mainFrame] frameView] setFrame:[resultWebView frame]];
1189 [resultWebView setNeedsDisplay:YES];
1197 - (NSString *)windowNibName
1199 // Override returning the nib file name of the document
1200 // 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.
1201 return @"MyDocument";
1204 - (void)windowControllerDidLoadNib:(NSWindowController *) aController
1209 NSSize errorDrawerSize;
1211 [super windowControllerDidLoadNib:aController];
1213 [resultImageView setImageFrameStyle:NSImageFramePhoto];
1214 [resultImageView setImageScaling:NSScaleNone];
1215 [resultImageView setImageAlignment:NSImageAlignCenter];
1216 [resultImageView setEditable:NO];
1218 [resultWebView setTextSizeMultiplier:0.9];
1220 warningIcon = [xmlWellFormedIcon image];
1222 [self updateCompleteUI];
1224 errorDrawerSize = [errorDrawer contentSize];
1225 errorDrawerSize.height = 130;
1226 [errorDrawer setContentSize:errorDrawerSize];
1228 NSFont *computerFont = [NSFont fontWithName:@"Courier" size:12.0];
1229 [resultView setFont:computerFont];
1231 [tabView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
1235 if (findPanelController == nil) {
1236 findPanelController = [[FindPanelController alloc] initWithWindowNibName:@"FindPanel"];
1237 // NSLog(@"init find panel controller: %@", findPanelController);
1240 if (jumpToLinePanelController == nil) {
1241 jumpToLinePanelController = [[JumpToLinePanelController alloc] initWithWindowNibName:@"JumpToLine"];
1242 // NSLog(@"init jump to line panel controller: %@", jumpToLinePanelController);
1245 if (unsavedChangesPanelController == nil) {
1246 unsavedChangesPanelController = [[UnsavedChangesPanelController alloc] initWithWindowNibName:@"UnsavedChanges"];
1247 // NSLog(@"init unsaved changes panel controller: %@", unsavedChangesPanelController);
1253 - (void)canCloseDocumentWithDelegate:(id)delegate shouldCloseSelector:(SEL)shouldCloseSelector contextInfo:(void *)contextInfo {
1255 [uiUpdateTimer invalidate];
1256 [super canCloseDocumentWithDelegate:delegate shouldCloseSelector:shouldCloseSelector contextInfo:contextInfo];
1266 - (IBAction)showErrorLocation:(id)sender {
1268 XMLTextView *textView;
1271 if ([processor errorSource] == XSLT_ERROR_SOURCE_XML) {
1272 [self selectTabById:XML];
1275 [self selectTabById:XSLT];
1276 textView = xsltView;
1279 errorLine = [processor errorLine];
1281 [textView selectLineByNumber:errorLine];
1285 - (NSData *)dataRepresentationOfType:(NSString *)aType
1287 // Insert code here to write your document from the given data. You can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.
1288 return [NSArchiver archivedDataWithRootObject:workset];
1291 - (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType
1293 // Insert code here to read your document from the given data. You can also choose to override -loadFileWrapperRepresentation:ofType: or -readFromFile:ofType: instead.
1296 workset = [[NSUnarchiver unarchiveObjectWithData:data] retain];
1297 [self updateCompleteUI];