diff --git a/macSVG/Cocoa Extensions/NSOutlineView_Extensions.m b/macSVG/Cocoa Extensions/NSOutlineView_Extensions.m index 443f506..65278a7 100644 --- a/macSVG/Cocoa Extensions/NSOutlineView_Extensions.m +++ b/macSVG/Cocoa Extensions/NSOutlineView_Extensions.m @@ -68,6 +68,11 @@ @implementation NSOutlineView(MyExtensions) +- (BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event +{ + return YES; +} + - (NSArray *)selectedItemsFlat { @@ -107,6 +112,10 @@ return items; } +- (NSArray *)selectedItems +{ + return [self selectedItemsFlat]; +} diff --git a/macSVG/MacSVG-Info.plist b/macSVG/MacSVG-Info.plist index 9e8f9ea..d83be29 100644 --- a/macSVG/MacSVG-Info.plist +++ b/macSVG/MacSVG-Info.plist @@ -105,7 +105,7 @@ CFBundleSignature ???? CFBundleVersion - 1649 + 1663 LSApplicationCategoryType public.app-category.graphics-design LSMinimumSystemVersion diff --git a/macSVG/SVGDocument Classes/XMLOutlineController.m b/macSVG/SVGDocument Classes/XMLOutlineController.m index 31316df..60c04db 100644 --- a/macSVG/SVGDocument Classes/XMLOutlineController.m +++ b/macSVG/SVGDocument Classes/XMLOutlineController.m @@ -569,6 +569,194 @@ } + + +//================================================================================== +// parseTransformAttribute +//================================================================================== + +- (NSMutableArray *)parseTransformAttribute:(NSString *)transformAttribute +{ + NSMutableArray * resultArray = [NSMutableArray array]; + + NSArray * transformComponentsArray = [transformAttribute componentsSeparatedByString:@")"]; + if (transformComponentsArray.count > 0) + { + for (NSString * aTransform in transformComponentsArray) + { + NSArray * aTransformComponentsArray = [aTransform componentsSeparatedByString:@"("]; + if (aTransformComponentsArray.count == 2) + { + NSCharacterSet * whitespaceCharacterSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; + + NSString * untrimmedCommandString = aTransformComponentsArray[0]; + NSString * commandString = [untrimmedCommandString + stringByTrimmingCharactersInSet:whitespaceCharacterSet]; + + BOOL validCommand = NO; + //NSUInteger expectedParameters = 0; + + if ([commandString isEqualToString:@"translate"] == YES) + { + validCommand = YES; + } + else if ([commandString isEqualToString:@"scale"] == YES) + { + validCommand = YES; + } + else if ([commandString isEqualToString:@"rotate"] == YES) + { + validCommand = YES; + } + else if ([commandString isEqualToString:@"matrix"] == YES) + { + validCommand = YES; + } + else if ([commandString isEqualToString:@"skewX"] == YES) + { + validCommand = YES; + } + else if ([commandString isEqualToString:@"skewY"] == YES) + { + validCommand = YES; + } + + if (validCommand == YES) + { + NSString * untrimmedValuesString = aTransformComponentsArray[1]; + NSString * valuesStringWithCommas = [untrimmedValuesString + stringByTrimmingCharactersInSet:whitespaceCharacterSet]; + NSMutableString * valuesString = [[NSMutableString alloc] + initWithString:valuesStringWithCommas]; + NSRange valuesStringRange = NSMakeRange(0, valuesString.length); + NSUInteger replaceCount = + [valuesString replaceOccurrencesOfString:@"," withString:@" " + options:0 range:valuesStringRange]; + #pragma unused(replaceCount) + + NSArray * valuesArray = [valuesString componentsSeparatedByString:@" "]; + + //NSLog(@"Found transform command %@ values:\n%@", commandString, valuesArray); + + NSMutableDictionary * transformDictionary = [[NSMutableDictionary alloc] init]; + + NSString * functionString = [[NSString alloc] initWithString:commandString]; + transformDictionary[@"function"] = functionString; + + NSUInteger valuesCount = valuesArray.count; + BOOL validValues = NO; + + if ([commandString isEqualToString:@"translate"] == YES) + { + if (valuesCount == 2) + { + validValues = YES; + NSString * xString = [[NSString alloc] initWithString:valuesArray[0]]; + transformDictionary[@"x"] = xString; + + NSString * yString = [[NSString alloc] initWithString:valuesArray[1]]; + transformDictionary[@"y"] = yString; + } + } + else if ([commandString isEqualToString:@"scale"] == YES) + { + if (valuesCount == 1) + { + validValues = YES; + NSString * xString = [[NSString alloc] initWithString:valuesArray[0]]; + transformDictionary[@"x"] = xString; + } + else if (valuesCount == 2) + { + validValues = YES; + NSString * xString = [[NSString alloc] initWithString:valuesArray[0]]; + transformDictionary[@"x"] = xString; + + NSString * yString = [[NSString alloc] initWithString:valuesArray[1]]; + transformDictionary[@"y"] = yString; + } + } + else if ([commandString isEqualToString:@"rotate"] == YES) + { + if (valuesCount == 1) + { + validValues = YES; + NSString * degreesString = [[NSString alloc] initWithString:valuesArray[0]]; + transformDictionary[@"degrees"] = degreesString; + } + else if (valuesCount == 3) + { + validValues = YES; + NSString * degreesString = [[NSString alloc] initWithString:valuesArray[0]]; + transformDictionary[@"degrees"] = degreesString; + + NSString * xString = [[NSString alloc] initWithString:valuesArray[1]]; + transformDictionary[@"x"] = xString; + + NSString * yString = [[NSString alloc] initWithString:valuesArray[2]]; + transformDictionary[@"y"] = yString; + } + } + else if ([commandString isEqualToString:@"matrix"] == YES) + { + if (valuesCount == 6) + { + validValues = YES; + NSString * m1String = [[NSString alloc] initWithString:valuesArray[0]]; + transformDictionary[@"m1"] = m1String; + + NSString * m2String = [[NSString alloc] initWithString:valuesArray[1]]; + transformDictionary[@"m2"] = m2String; + + NSString * m3String = [[NSString alloc] initWithString:valuesArray[2]]; + transformDictionary[@"m3"] = m3String; + + NSString * m4String = [[NSString alloc] initWithString:valuesArray[3]]; + transformDictionary[@"m4"] = m4String; + + NSString * m5String = [[NSString alloc] initWithString:valuesArray[4]]; + transformDictionary[@"m5"] = m5String; + + NSString * m6String = [[NSString alloc] initWithString:valuesArray[5]]; + transformDictionary[@"m6"] = m6String; + } + } + else if ([commandString isEqualToString:@"skewX"] == YES) + { + if (valuesCount == 1) + { + validValues = YES; + NSString * xString = [[NSString alloc] initWithString:valuesArray[0]]; + transformDictionary[@"degrees"] = xString; + } + } + else if ([commandString isEqualToString:@"skewY"] == YES) + { + if (valuesCount == 1) + { + validValues = YES; + NSString * yString = [[NSString alloc] initWithString:valuesArray[0]]; + transformDictionary[@"degrees"] = yString; + } + } + + if (validValues == YES) + { + [resultArray addObject:transformDictionary]; + } + } + } + } + } + + return resultArray; +} + + + + + + //================================================================================== // customizeAnimateTransform:forParentElement: //================================================================================== @@ -594,25 +782,254 @@ DOMElement * domParentElement = [self.macSVGDocumentWindowController.svgWebKitController domElementForMacsvgid:parentMacsvgid]; - NSRect boundingBox = [webKitInterface bBoxForDOMElement:domParentElement]; + NSString * parentTransformString = [domParentElement getAttribute:@"transform"]; - if (NSIsEmptyRect(boundingBox) == NO) + BOOL useDefaultTransform = YES; + + if (parentTransformString != NULL) { - CGFloat midX = NSMidX(boundingBox); - CGFloat midY = NSMidY(boundingBox); + NSMutableArray * parentTransformsArray = [self parseTransformAttribute:parentTransformString]; - NSString * midXString = [self allocFloatString:midX]; - NSString * midYString = [self allocFloatString:midY]; - - NSString * rotateValuesString = [NSString stringWithFormat:@"0 %@ %@;360 %@ %@", - midXString, midYString, midXString, midYString]; - - NSXMLNode * valuesNode = [prototypeElement attributeForName:@"values"]; - if (valuesNode != NULL) + if (parentTransformsArray.count > 0) { - valuesNode.stringValue = rotateValuesString; + NSInteger lastTransformIndex = parentTransformsArray.count - 1; + + NSDictionary * parentTransformDictionary = [parentTransformsArray objectAtIndex:lastTransformIndex]; + NSString * transformFunctionString = [parentTransformDictionary objectForKey:@"function"]; + + + if ([transformFunctionString isEqualToString:@"translate"] == YES) + { + NSString * translateXString = [parentTransformDictionary objectForKey:@"x"]; + NSString * translateYString = [parentTransformDictionary objectForKey:@"y"]; + + if ((translateXString.length > 0) && (translateYString.length > 0)) + { + NSXMLNode * typeNode = [prototypeElement attributeForName:@"type"]; + [typeNode setStringValue:@"translate"]; + + NSXMLNode * durNode = [prototypeElement attributeForName:@"dur"]; + [durNode setStringValue:@"3s"]; + + CGFloat translateX = translateXString.floatValue; + CGFloat endTranslateX = translateX + 20.0f; + + CGFloat translateY = translateYString.floatValue; + CGFloat endTranslateY = translateY + 20.0f; + + NSString * endTranslateXString = [self allocFloatString:endTranslateX]; + NSString * endTranslateYString = [self allocFloatString:endTranslateY]; + + NSString * rotateValuesString = [NSString stringWithFormat:@"%@ %@; %@ %@; %@ %@;", + translateXString, translateYString, + endTranslateXString, endTranslateYString, + translateXString, translateYString]; + + NSXMLNode * valuesNode = [prototypeElement attributeForName:@"values"]; + if (valuesNode != NULL) + { + valuesNode.stringValue = rotateValuesString; + } + + resultString = prototypeElement.XMLString; + + useDefaultTransform = NO; + } + } + + if ([transformFunctionString isEqualToString:@"scale"] == YES) + { + NSString * scaleXString = [parentTransformDictionary objectForKey:@"x"]; + NSString * scaleYString = [parentTransformDictionary objectForKey:@"y"]; + + if ((scaleXString.length > 0) && (scaleYString.length > 0)) + { + NSXMLNode * typeNode = [prototypeElement attributeForName:@"type"]; + [typeNode setStringValue:@"scale"]; + + NSXMLNode * durNode = [prototypeElement attributeForName:@"dur"]; + [durNode setStringValue:@"3s"]; + + CGFloat scaleX = scaleXString.floatValue; + CGFloat endScaleX = scaleX * 1.2f; + + CGFloat scaleY = scaleYString.floatValue; + CGFloat endScaleY = scaleY * 1.2f; + + NSString * endScaleXString = [self allocFloatString:endScaleX]; + NSString * endScaleYString = [self allocFloatString:endScaleY]; + + NSString * scaleValuesString = [NSString stringWithFormat:@"%@ %@; %@ %@; %@ %@;", + scaleXString, scaleYString, + endScaleXString, endScaleYString, + scaleXString, scaleYString]; + + NSXMLNode * valuesNode = [prototypeElement attributeForName:@"values"]; + if (valuesNode != NULL) + { + valuesNode.stringValue = scaleValuesString; + } + + resultString = prototypeElement.XMLString; + + useDefaultTransform = NO; + } + } - resultString = prototypeElement.XMLString; + else if ([transformFunctionString isEqualToString:@"rotate"] == YES) + { + NSString * rotateDegreesString = [parentTransformDictionary objectForKey:@"degrees"]; + NSString * rotateXString = [parentTransformDictionary objectForKey:@"x"]; + NSString * rotateYString = [parentTransformDictionary objectForKey:@"y"]; + + if ((rotateDegreesString.length > 0) && (rotateXString.length > 0) && (rotateYString.length > 0)) + { + NSXMLNode * typeNode = [prototypeElement attributeForName:@"type"]; + [typeNode setStringValue:@"rotate"]; + + CGFloat rotateDegrees = rotateDegreesString.floatValue; + CGFloat endRotateDegrees = rotateDegrees + 360.0f; + + NSString * endRotateDegreesString = [self allocFloatString:endRotateDegrees]; + + NSString * rotateValuesString = [NSString stringWithFormat:@"%@ %@ %@; %@ %@ %@;", + rotateDegreesString, rotateXString, rotateYString, + endRotateDegreesString, rotateXString, rotateYString]; + + NSXMLNode * valuesNode = [prototypeElement attributeForName:@"values"]; + if (valuesNode != NULL) + { + valuesNode.stringValue = rotateValuesString; + } + + resultString = prototypeElement.XMLString; + + useDefaultTransform = NO; + } + } + + else if ([transformFunctionString isEqualToString:@"skewX"] == YES) + { + NSString * skewXDegreesString = [parentTransformDictionary objectForKey:@"degrees"]; + + if (skewXDegreesString.length > 0) + { + NSXMLNode * typeNode = [prototypeElement attributeForName:@"type"]; + [typeNode setStringValue:@"skewX"]; + + NSXMLNode * durNode = [prototypeElement attributeForName:@"dur"]; + [durNode setStringValue:@"3s"]; + + CGFloat skewXDegrees = skewXDegreesString.floatValue; + CGFloat endSkewXDegrees = skewXDegrees + 10.0f; + + NSString * endSkewXDegreesString = [self allocFloatString:endSkewXDegrees]; + + NSString * skewXValuesString = [NSString stringWithFormat:@"%@; %@; %@;", + skewXDegreesString, endSkewXDegreesString, skewXDegreesString]; + + NSXMLNode * valuesNode = [prototypeElement attributeForName:@"values"]; + if (valuesNode != NULL) + { + valuesNode.stringValue = skewXValuesString; + } + + resultString = prototypeElement.XMLString; + + useDefaultTransform = NO; + } + } + + else if ([transformFunctionString isEqualToString:@"skewY"] == YES) + { + NSString * skewYDegreesString = [parentTransformDictionary objectForKey:@"degrees"]; + + if (skewYDegreesString.length > 0) + { + NSXMLNode * typeNode = [prototypeElement attributeForName:@"type"]; + [typeNode setStringValue:@"skewY"]; + + NSXMLNode * durNode = [prototypeElement attributeForName:@"dur"]; + [durNode setStringValue:@"3s"]; + + CGFloat skewYDegrees = skewYDegreesString.floatValue; + CGFloat endSkewYDegrees = skewYDegrees + 10.0f; + + NSString * endSkewYDegreesString = [self allocFloatString:endSkewYDegrees]; + + NSString * skewYValuesString = [NSString stringWithFormat:@"%@; %@; %@;", + skewYDegreesString, endSkewYDegreesString, skewYDegreesString]; + + NSXMLNode * valuesNode = [prototypeElement attributeForName:@"values"]; + if (valuesNode != NULL) + { + valuesNode.stringValue = skewYValuesString; + } + + resultString = prototypeElement.XMLString; + + useDefaultTransform = NO; + } + } + + else if ([transformFunctionString isEqualToString:@"matrix"] == YES) + { + NSString * matrixM1String = [parentTransformDictionary objectForKey:@"m1"]; + NSString * matrixM2String = [parentTransformDictionary objectForKey:@"m2"]; + NSString * matrixM3String = [parentTransformDictionary objectForKey:@"m3"]; + NSString * matrixM4String = [parentTransformDictionary objectForKey:@"m4"]; + NSString * matrixM5String = [parentTransformDictionary objectForKey:@"m5"]; + NSString * matrixM6String = [parentTransformDictionary objectForKey:@"m6"]; + + if ((matrixM1String.length > 0) && (matrixM2String.length > 0) && (matrixM3String.length > 0) && (matrixM4String.length > 0) && (matrixM5String.length > 0) && (matrixM6String.length > 0)) + { + NSXMLNode * typeNode = [prototypeElement attributeForName:@"type"]; + [typeNode setStringValue:@"matrix"]; + + NSXMLNode * durNode = [prototypeElement attributeForName:@"dur"]; + [durNode setStringValue:@"3s"]; + + // no changes applied to matrix, the same matrix is used twice as value + NSString * matrixValuesString = [NSString stringWithFormat:@"%@ %@ %@ %@ %@ %@; %@ %@ %@ %@ %@ %@; ", + matrixM1String, matrixM2String, matrixM3String, matrixM4String, matrixM5String, matrixM6String, + matrixM1String, matrixM2String, matrixM3String, matrixM4String, matrixM5String, matrixM6String]; + + NSXMLNode * valuesNode = [prototypeElement attributeForName:@"values"]; + if (valuesNode != NULL) + { + valuesNode.stringValue = matrixValuesString; + } + + resultString = prototypeElement.XMLString; + + useDefaultTransform = NO; + } + } + } + } + + if (useDefaultTransform == YES) + { + NSRect boundingBox = [webKitInterface bBoxForDOMElement:domParentElement]; + + if (NSIsEmptyRect(boundingBox) == NO) + { + CGFloat midX = NSMidX(boundingBox); + CGFloat midY = NSMidY(boundingBox); + + NSString * midXString = [self allocFloatString:midX]; + NSString * midYString = [self allocFloatString:midY]; + + NSString * rotateValuesString = [NSString stringWithFormat:@"0 %@ %@;360 %@ %@", + midXString, midYString, midXString, midYString]; + + NSXMLNode * valuesNode = [prototypeElement attributeForName:@"values"]; + if (valuesNode != NULL) + { + valuesNode.stringValue = rotateValuesString; + + resultString = prototypeElement.XMLString; + } } } } @@ -621,7 +1038,7 @@ } //================================================================================== -// customizeAnimateTransform:forParentElement: +// customizeAnimateMotion:forParentElement: //================================================================================== - (NSString *)customizeAnimateMotion:(NSString *)xmlElementPrototypeString forParentElement:(NSXMLElement *)parentElement @@ -2399,6 +2816,8 @@ [checkboxButton setTarget:self]; [checkboxButton setAction:@selector(visibilityCheckboxAction:)]; + checkboxButton.refusesFirstResponder = YES; + resultView = checkboxButton; } else if ([tableColumnIdentifier isEqualToString:COLUMNID_IS_LOCKED] == YES) @@ -2406,6 +2825,8 @@ NSButton * checkboxButton = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 18, 18)]; [checkboxButton setButtonType:NSSwitchButton]; [checkboxButton setControlSize:NSControlSizeSmall]; + + checkboxButton.refusesFirstResponder = YES; resultView = checkboxButton; } @@ -2421,6 +2842,7 @@ //NSTextField * textField = [[NSTextField alloc] initWithFrame:outlineView.frame]; NSTextField * textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 4, 300, 14)]; textField.identifier = tableColumn.identifier; + textField.refusesFirstResponder = YES; [textField setControlSize:NSControlSizeSmall]; textField.font = [NSFont systemFontOfSize:10]; textField.bordered = NO;