From 3eb7fa7acee5c91c4da3ec072eb2b710bb567d3a Mon Sep 17 00:00:00 2001 From: dsward2 Date: Tue, 21 Nov 2017 03:03:53 -0600 Subject: [PATCH] These changes are intended to improve the initial settings for the AnimateTransform element. When a new AnimateTransform element is added to the SVG document, the parent element of the AnimateTransform element will be checked for a "transform" attribute. If the transform attribute is present in the parent element, the last transform operation will be used to set the attributes in the AnimateTransform element accordingly. For example, if the parent element's transform attribute is set to "rotate(45, 37, 58)", the "type" attribute in the AnimateTransform element will be set to "rotate", and the "values" attribute in the AnimateTransform will be based on the parent element's rotate values. For the animation, the starting degrees value will match the parent's rotate value, and the center of rotation will match the parent's. An additional set of values will be added to rotate the parent element a full 360 degrees. The other transform operations (translate, scale, skewX, skewY) will produce similar results for new AnimateTransform elements. For a "matrix" transform, the starting and ending matrix values are the same, but can be modified in the editor after the AnimateTransform element is added. --- .../NSOutlineView_Extensions.m | 9 + macSVG/MacSVG-Info.plist | 2 +- .../XMLOutlineController.m | 452 +++++++++++++++++- 3 files changed, 447 insertions(+), 16 deletions(-) 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;