Files
macSVG-mirror/macSVG/SVGDocument Classes/DOMSelectionControlsManager.m

3125 lines
139 KiB
Objective-C

//
// DOMSelectionControlsManager.m
// macSVG
//
// Created by Douglas Ward on 9/9/13.
//
//
#import "DOMSelectionControlsManager.h"
#import <WebKit/WebKit.h>
#import <JavaScriptCore/JavaScriptCore.h>
#import <MacSVGPlugin/MacSVGPlugin.h>
#import "MacSVGDocumentWindowController.h"
#import "MacSVGDocument.h"
#import "SVGXMLDOMSelectionManager.h"
#import "SVGWebKitController.h"
#import "SVGWebView.h"
#import "MacSVGAppDelegate.h"
//#import "WebKitInterface.h"
#import "DOMSelectionCacheRecord.h"
#import "SelectedElementsManager.h"
#import "ToolSettingsPopoverViewController.h"
#import "PathFunctions.h"
#import "SVGPathEditor.h"
#import "SVGPolylineEditor.h"
#import "SVGLineEditor.h"
#import "DOMMouseEventsController.h"
#import "AnimationTimelineView.h"
#import "EditorUIFrameController.h"
#import "ElementEditorPlugInController.h"
#import "PathSegment.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@implementation DOMSelectionControlsManager
//==================================================================================
// dealloc
//==================================================================================
- (void)dealloc
{
self.validElementsForTransformDictionary = NULL;
self.domElementForHandles = NULL;
self.domElementForHandlesCreationTime = 0;
}
//==================================================================================
// init
//==================================================================================
- (instancetype)init
{
self = [super init];
if (self)
{
// Initialization code here.
self.validElementsForTransformDictionary = @{@"rect": @"rect",
@"circle": @"circle",
@"ellipse": @"ellipse",
@"text": @"text",
@"image": @"image",
@"line": @"line",
@"polyline": @"polyline",
@"polygon": @"polygon",
@"path": @"path",
@"use": @"use",
@"g": @"g",
@"foreignObject": @"foreignObject"};
self.domElementForHandles = NULL;
self.domElementForHandlesCreationTime = 0;
}
return self;
}
//==================================================================================
// macsvgTopGroupElement
//==================================================================================
- (DOMElement *)macsvgTopGroupElement
{
// find _macsvg_top_group in top level svg element
DOMElement * macsvgTopGroupElement = NULL;
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
DOMElement * domDocumentElement = domDocument.documentElement;
if ([domDocumentElement isKindOfClass:[DOMHTMLElement class]] == YES)
{
// this is an XHTML element - search for an SVG element inside
DOMNodeList * svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
if (svgElementsList.length > 0)
{
domDocumentElement = (DOMElement *)[svgElementsList item:0];
}
else
{
domDocumentElement = NULL;
}
}
if (domDocumentElement != NULL)
{
DOMNodeList * childNodes = domDocumentElement.childNodes;
unsigned int childCount = childNodes.length;
NSInteger foundIndex = -1;
for (int i = childCount - 1; i >= 0; i--)
{
DOMNode * aChildNode = [childNodes item:i];
unsigned short childNodeType = aChildNode.nodeType;
if (childNodeType == DOM_ELEMENT_NODE)
{
DOMElement * aChildElement = (DOMElement *)aChildNode;
NSString * idString = [aChildElement getAttribute:@"id"];
if ([idString isEqualToString:@"_macsvg_top_group"] == YES)
{
macsvgTopGroupElement = aChildElement;
foundIndex = i;
break;
}
}
}
if (macsvgTopGroupElement == NULL)
{
macsvgTopGroupElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"g"];
[macsvgTopGroupElement setAttributeNS:NULL qualifiedName:@"id" value:@"_macsvg_top_group"];
[macsvgTopGroupElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_top_group"];
[domDocumentElement appendChild:macsvgTopGroupElement];
}
else
{
if (foundIndex != (childCount - 1))
{
// move macsvgTopGroupElement to final child element in document
[domDocumentElement removeChild:macsvgTopGroupElement];
[domDocumentElement appendChild:macsvgTopGroupElement];
}
}
}
return macsvgTopGroupElement;
}
//==================================================================================
// getMacsvgTopGroupChildByID:createIfNew:
//==================================================================================
- (DOMElement *)getMacsvgTopGroupChildByID:(NSString *)idString createIfNew:(BOOL)createIfNew
{
DOMElement * resultElement = NULL;
DOMElement * macsvgTopGroupElement = [self macsvgTopGroupElement];
DOMNodeList * childNodes = macsvgTopGroupElement.childNodes;
unsigned int childCount = childNodes.length;
for (int i = 0; i < childCount; i++)
{
DOMNode * aChildNode = [childNodes item:i];
unsigned short childNodeType = aChildNode.nodeType;
if (childNodeType == DOM_ELEMENT_NODE)
{
DOMElement * aChildElement = (DOMElement *)aChildNode;
NSString * aIDString = [aChildElement getAttribute:@"id"];
if ([idString isEqualToString:aIDString] == YES)
{
resultElement = aChildElement;
break;
}
}
}
if (resultElement == NULL)
{
if (createIfNew == YES)
{
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
macsvgTopGroupElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"g"];
[macsvgTopGroupElement setAttributeNS:NULL qualifiedName:@"id" value:idString];
[macsvgTopGroupElement setAttributeNS:NULL qualifiedName:@"class" value:idString];
[macsvgTopGroupElement appendChild:macsvgTopGroupElement];
}
}
return resultElement;
}
//==================================================================================
// setMacsvgTopGroupChildByID
//==================================================================================
- (void)setMacsvgTopGroupChild:(DOMElement *)childElement
{
NSString * idString = [childElement getAttribute:@"id"];
//if ([idString isEqualToString:@"_macsvg_selectedRectsGroup"] == YES)
//{
// NSLog(@"setMacsvgTopGroupChild - _macsvg_selectedRectsGroup");
//}
DOMElement * existingChildElement = [self getMacsvgTopGroupChildByID:idString createIfNew:NO];
if (existingChildElement != NULL)
{
DOMElement * parentElement = existingChildElement.parentElement;
[parentElement replaceChild:childElement oldChild:existingChildElement];
}
else
{
// inject new pathHandlesGroup
DOMElement * macsvgTopGroupElement = [self macsvgTopGroupElement];
[macsvgTopGroupElement appendChild:childElement];
}
}
//==================================================================================
// removeMacsvgTopGroupChildByID:
//==================================================================================
- (void)removeMacsvgTopGroupChildByID:(NSString *)idString
{
//if ([idString isEqualToString:@"_macsvg_selectedRectsGroup"] == YES)
//{
// NSLog(@"removeMacsvgTopGroupChildByID - _macsvg_selectedRectsGroup");
//}
DOMElement * macsvgTopGroupElement = [self macsvgTopGroupElement];
DOMNodeList * childNodes = macsvgTopGroupElement.childNodes;
unsigned int childCount = childNodes.length;
for (int i = 0; i < childCount; i++)
{
DOMNode * aChildNode = [childNodes item:i];
unsigned short childNodeType = aChildNode.nodeType;
if (childNodeType == DOM_ELEMENT_NODE)
{
DOMElement * aChildElement = (DOMElement *)aChildNode;
NSString * childIDString = [aChildElement getAttribute:@"id"];
if ([idString isEqualToString:childIDString] == YES)
{
[aChildElement.parentElement removeChild:aChildElement];
break;
}
}
}
}
//==================================================================================
// removeMacsvgTopGroupChildByClass:
//==================================================================================
- (void)removeMacsvgTopGroupChildByClass:(NSString *)classString
{
DOMElement * macsvgTopGroupElement = [self macsvgTopGroupElement];
DOMNodeList * childNodes = macsvgTopGroupElement.childNodes;
unsigned int childCount = childNodes.length;
BOOL searchCompleted = NO;
for (int i = 0; i < childCount; i++)
{
DOMNode * aChildNode = [childNodes item:i];
unsigned short childNodeType = aChildNode.nodeType;
if (childNodeType == DOM_ELEMENT_NODE)
{
DOMElement * aChildElement = (DOMElement *)aChildNode;
NSString * childClassesString = [aChildElement getAttribute:@"class"];
NSArray * childClassesArray = [childClassesString componentsSeparatedByString:@" "];
for (NSString * childClassString in childClassesArray)
{
if ([classString isEqualToString:childClassString] == YES)
{
[aChildElement.parentElement removeChild:aChildElement];
searchCompleted = YES;
break;
}
}
if (searchCompleted == YES)
{
break;
}
}
}
}
//==================================================================================
// copyChildAnimationFromDOMElement:toDOMElement:
//==================================================================================
-(void) copyChildAnimationFromDOMElement:(DOMElement *)sourceElement toDOMElement:(DOMElement *)destinationElement
offsetPoint:(NSPoint)offsetPoint
{
//NSLog(@"enter copyChildAnimationFromElement:toElement:");
NSInteger animationEnabled = macSVGDocumentWindowController.enableAnimationCheckbox.state;
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
// copy transform attribute attached to source element, if present
NSString * transformValue = [sourceElement getAttribute:@"transform"];
if (transformValue != NULL)
{
if (transformValue.length > 0)
{
[destinationElement setAttributeNS:NULL qualifiedName:@"transform" value:transformValue];
}
}
DOMNodeList * childNodes = sourceElement.childNodes;
unsigned int childCount = childNodes.length;
NSCharacterSet * delimitersCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@" ,;"];
for (int i = 0; i < childCount; i++)
{
DOMNode * aChildNode = [childNodes item:i];
unsigned short childNodeType = aChildNode.nodeType;
if (childNodeType == DOM_ELEMENT_NODE)
{
DOMElement * aChildElement = (DOMElement *)aChildNode;
NSString * childElementName = aChildElement.nodeName;
BOOL isAnimationElement = NO;
if ([childElementName isEqualToString:@"set"] == YES)
{
isAnimationElement = YES;
}
else if ([childElementName isEqualToString:@"animate"] == YES)
{
isAnimationElement = YES;
}
else if ([childElementName isEqualToString:@"animateMotion"] == YES)
{
isAnimationElement = YES;
}
else if ([childElementName isEqualToString:@"animateTransform"] == YES)
{
isAnimationElement = YES;
}
if (isAnimationElement == YES)
{
// copy a matching animation element to the selection rectangle, hopefully in sync with original element
DOMElement * controlAnimationElement = [domDocument createElementNS:svgNamespace
qualifiedName:childElementName];
DOMNamedNodeMap * attributesNodeMap = aChildNode.attributes;
unsigned int a, attCount = attributesNodeMap.length;
NSString * beginValue = @"0s;";
for (a = 0; a < attCount; a++)
{
DOMNode * attributeNode = [attributesNodeMap item:a];
NSString * attributeName = [attributeNode.nodeName copy];
NSString * attributeValue = [attributeNode.nodeValue copy];
if ([attributeName isEqualToString:@"begin"] == YES)
{
beginValue = attributeValue;
}
if ([attributeName isEqualToString:@"macsvgid"] == YES)
{
attributeName = @"control_Macsvgid";
}
if ([attributeName isEqualToString:@"id"] == YES)
{
attributeValue = [NSString stringWithFormat:@"_macsvg_control_%@", attributeValue];
}
[controlAnimationElement setAttributeNS:NULL qualifiedName:attributeName value:attributeValue]; // TEST 20160810 reverted
//[controlAnimationElement setAttributeNS:svgNamespace qualifiedName:attName value:attValue]; // TEST 20160806
}
if (animationEnabled != 0) // 20161014
{
NSString * sourceElementTag = [sourceElement tagName];
BOOL isCircleOrEllipse = NO;
if ([sourceElementTag isEqualToString:@"circle"] == YES)
{
isCircleOrEllipse = YES;
}
if ([sourceElementTag isEqualToString:@"ellipse"] == YES)
{
isCircleOrEllipse = YES;
}
if (isCircleOrEllipse == YES)
{
if ([childElementName isEqualToString:@"animate"] == YES)
{
NSString * animateAttributeName = [aChildElement getAttribute:@"attributeName"];
NSString * animateValues = [aChildElement getAttribute:@"values"];
if ([animateValues length] > 0)
{
NSString * radiusString = NULL;
if ([sourceElementTag isEqualToString:@"circle"] == YES)
{
radiusString = [sourceElement getAttribute:@"r"];
}
else if ([sourceElementTag isEqualToString:@"ellipse"] == YES)
{
if ([animateAttributeName isEqualToString:@"cx"] == YES)
{
radiusString = [sourceElement getAttribute:@"rx"];
}
else if ([animateAttributeName isEqualToString:@"cy"] == YES)
{
radiusString = [sourceElement getAttribute:@"ry"];
}
}
if (radiusString != NULL)
{
float radiusFloat = [radiusString floatValue];
NSString * newAttributeName = NULL;
if ([animateAttributeName isEqualToString:@"cx"] == YES)
{
newAttributeName = @"x";
}
else if ([animateAttributeName isEqualToString:@"cy"] == YES)
{
newAttributeName = @"y";
}
if (newAttributeName != NULL)
{
NSString * strokeWidthString = [sourceElement getAttribute:@"stroke-width"];
if ([strokeWidthString length] == 0)
{
strokeWidthString = @"0";
}
float strokeWidth = strokeWidthString.floatValue;
[controlAnimationElement setAttribute:@"attributeName" value:newAttributeName];
NSArray * animateValuesArray = [animateValues componentsSeparatedByCharactersInSet:delimitersCharacterSet];
NSMutableString * newValuesString = [NSMutableString string];
for (NSString * aAnimateValue in animateValuesArray)
{
if ([aAnimateValue length] > 0)
{
float aAnimateValueFloat = [aAnimateValue floatValue];
aAnimateValueFloat -= radiusFloat;
aAnimateValueFloat -= strokeWidth / 2.0f;
if ([animateAttributeName isEqualToString:@"cx"] == YES)
{
aAnimateValueFloat += offsetPoint.x;
}
else if ([animateAttributeName isEqualToString:@"cy"] == YES)
{
aAnimateValueFloat += offsetPoint.y;
}
if (newValuesString.length > 0)
{
[newValuesString appendString:@"; "];
}
[newValuesString appendFormat:@"%f", aAnimateValueFloat];
}
}
[controlAnimationElement setAttribute:@"values" value:newValuesString];
}
}
}
}
}
else
{
// adjust animate values for rectangular objects
if ([childElementName isEqualToString:@"animate"] == YES)
{
NSString * animateAttributeName = [aChildElement getAttribute:@"attributeName"];
NSString * animateValues = [aChildElement getAttribute:@"values"];
if ([animateValues length] > 0)
{
NSString * strokeWidthString = [sourceElement getAttribute:@"stroke-width"];
if ([strokeWidthString length] == 0)
{
strokeWidthString = @"0";
}
float strokeWidth = strokeWidthString.floatValue;
NSArray * animateValuesArray = [animateValues componentsSeparatedByCharactersInSet:delimitersCharacterSet];
NSMutableString * newValuesString = [NSMutableString string];
for (NSString * aAnimateValue in animateValuesArray)
{
if ([aAnimateValue length] > 0)
{
float aAnimateValueFloat = [aAnimateValue floatValue];
aAnimateValueFloat -= strokeWidth / 2.0f;
//aAnimateValueFloat -= 1.0f;
if ([animateAttributeName isEqualToString:@"x"] == YES)
{
aAnimateValueFloat += offsetPoint.x;
}
else if ([animateAttributeName isEqualToString:@"y"] == YES)
{
aAnimateValueFloat += offsetPoint.y;
}
if (newValuesString.length > 0)
{
[newValuesString appendString:@"; "];
}
[newValuesString appendFormat:@"%f", aAnimateValueFloat];
}
}
[controlAnimationElement setAttribute:@"values" value:newValuesString];
}
}
}
}
[controlAnimationElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_controlAnimation"];
[destinationElement appendChild:controlAnimationElement];
[controlAnimationElement setAttributeNS:NULL qualifiedName:@"begin" value:beginValue]; // enable animation for element in webkit
}
}
}
//NSLog(@"exit copyChildAnimationFromElement:toElement:");
}
//==================================================================================
// removeDOMSelectionRectsAndHandles
//==================================================================================
-(void) removeDOMSelectionRectsAndHandles
{
[self removeMacsvgTopGroupChildByID:@"_macsvg_selectionHandlesGroup"];
self.domElementForHandles = NULL;
self.domElementForHandlesCreationTime = 0;
[self removeMacsvgTopGroupChildByID:@"_macsvg_selectedRectsGroup"];
// remove any superimposed highlights, if the highlight segment checkbox option was enabled to create those
[self removeMacsvgTopGroupChildByID:@"_macsvg_highlightPathSegmentGroup"];
[self removeMacsvgTopGroupChildByID:@"_macsvg_highlightPolylinePointGroup"];
[self removeMacsvgTopGroupChildByID:@"_macsvg_highlightLinePointGroup"];
//[self removeMacsvgTopGroupChildByID:@"_macsvg_lineHandlesGroup"];
//[self removeMacsvgTopGroupChildByID:@"_macsvg_polylineHandlesGroup"];
//[self removeMacsvgTopGroupChildByID:@"_macsvg_pathHandlesGroup"];
//[self removeDOMPathSegmentHighlight]; // TEST 20160905
}
//==================================================================================
// makeDOMSelectionRects
//==================================================================================
-(void) makeDOMSelectionRects
{
//NSLog(@"enter makeDOMSelectionRects");
MacSVGAppDelegate * macSVGAppDelegate = (MacSVGAppDelegate *)NSApp.delegate;
WebKitInterface * webKitInterface = [macSVGAppDelegate webKitInterface];
[svgXMLDOMSelectionManager resyncDOMElementsInSelectedElementsArray];
[self removeDOMSelectionRectsAndHandles];
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
DOMElement * newSelectedRectsGroup = [domDocument createElementNS:svgNamespace
qualifiedName:@"g"];
[newSelectedRectsGroup setAttributeNS:NULL qualifiedName:@"id" value:@"_macsvg_selectedRectsGroup"];
[newSelectedRectsGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectedRectsGroup"];
NSMutableArray * commonParentElementsArray = [[NSMutableArray alloc] init];
// create bounding boxes for selected items
NSUInteger selectedItemsCount = [svgXMLDOMSelectionManager.selectedElementsManager selectedElementsCount];
for (NSInteger i = 0; i < selectedItemsCount; i++)
{
DOMElement * aSelectedSvgElement = [svgXMLDOMSelectionManager.selectedElementsManager domElementAtIndex:i];
NSRect boundingBox = NSZeroRect;
NSString * elementName = aSelectedSvgElement.nodeName;
id validElement = (self.validElementsForTransformDictionary)[elementName];
MacSVGDocument * macSVGDocument = macSVGDocumentWindowController.document;
if ([macSVGDocument.fileNameExtension isEqualToString:@"xhtml"] == YES)
{
if ([aSelectedSvgElement isKindOfClass:[DOMElement class]] == YES)
{
validElement = elementName;
}
}
if (validElement != NULL)
{
boundingBox = [webKitInterface bBoxForDOMElement:aSelectedSvgElement];
if (NSIsEmptyRect(boundingBox) == YES)
{
if ([macSVGDocument.fileNameExtension isEqualToString:@"xhtml"] == YES)
{
/*
int xResult = [aSelectedSvgElement offsetTop];
int yResult = [aSelectedSvgElement offsetLeft];
int widthResult = [aSelectedSvgElement offsetWidth];
int heightResult = [aSelectedSvgElement offsetHeight];
boundingBox = NSMakeRect(xResult, yResult, widthResult, heightResult);
*/
/*
WebScriptObject * result = [domHTMLElement callWebScriptMethod:@"getBoundingClientRect" withArguments:NULL];
id clientRectFunction = [NSString stringWithFormat:
@"function f() {var element = document.getElementById('%@'); return element.getBoundingClientRect();} f();",
@"text1"];
NSString * clientRect = [svgWebView stringByEvaluatingJavaScriptFromString:clientRectFunction];
NSLog(@"%@", clientRect);
*/
/*
JSPropertyNameArrayRef properties =
JSObjectCopyPropertyNames([[svgWebView mainFrame] globalContext],
[aSelectedSvgElement JSObject]);
size_t count = JSPropertyNameArrayGetCount(properties);
for (NSInteger i = 0; i < count; i++)
{
JSStringRef property = JSPropertyNameArrayGetNameAtIndex(properties, i);
// ... etc. as above
NSString * propertyString = CFBridgingRelease(JSStringCopyCFString( kCFAllocatorDefault, property ));
NSString * valueString = [aSelectedSvgElement valueForKey:propertyString];
NSLog(@"%@=%@", propertyString, valueString);
}
*/
// TODO: FIXME: Currently, we can select HTML elements, but cannot get the client rect or offset rect
// not sure that information is available for inline layouts
}
}
if ([elementName isEqualToString:@"use"])
{
NSString * xAttributeString = [aSelectedSvgElement getAttribute:@"x"];
NSString * yAttributeString = [aSelectedSvgElement getAttribute:@"y"];
NSString * widthAttributeString = [aSelectedSvgElement getAttribute:@"width"];
NSString * heightAttributeString = [aSelectedSvgElement getAttribute:@"height"];
float xAttributeFloat = xAttributeString.floatValue;
float yAttributeFloat = yAttributeString.floatValue;
float widthAttributeFloat = widthAttributeString.floatValue;
float heightAttributeFloat = heightAttributeString.floatValue;
boundingBox.origin.x += xAttributeFloat;
boundingBox.origin.y += yAttributeFloat;
boundingBox.size.width = widthAttributeFloat;
boundingBox.size.height = heightAttributeFloat;
}
if ([elementName isEqualToString:@"foreignObject"])
{
NSString * xAttributeString = [aSelectedSvgElement getAttribute:@"x"];
NSString * yAttributeString = [aSelectedSvgElement getAttribute:@"y"];
NSString * widthAttributeString = [aSelectedSvgElement getAttribute:@"width"];
NSString * heightAttributeString = [aSelectedSvgElement getAttribute:@"height"];
float xAttributeFloat = xAttributeString.floatValue;
float yAttributeFloat = yAttributeString.floatValue;
float widthAttributeFloat = widthAttributeString.floatValue;
float heightAttributeFloat = heightAttributeString.floatValue;
boundingBox.origin.x = xAttributeFloat;
boundingBox.origin.y = yAttributeFloat;
boundingBox.size.width = widthAttributeFloat;
boundingBox.size.height = heightAttributeFloat;
}
if (NSIsEmptyRect(boundingBox) == YES)
{
if (svgWebKitController.mainFrameIsLoading == YES)
{
//NSLog(@"SVGXMLDOMSelectionManager boundingBox is empty, mainFrameIsLoading=YES %@", aSelectedSvgElement);
}
else
{
//NSLog(@"SVGXMLDOMSelectionManager boundingBox is empty, mainFrameIsLoading=NO %@", aSelectedSvgElement);
}
}
DOMElement * parentElement = (id)aSelectedSvgElement.parentNode;
DOMElement * controlParentElement = NULL;
if (commonParentElementsArray.count > 0)
{
// check for an existing controls group for this level of the structure
BOOL continueSearch = YES;
NSUInteger parentIndex = 0;
while (continueSearch == YES)
{
DOMSelectionCacheRecord * domSelectionCacheRecord = commonParentElementsArray[parentIndex];
if (domSelectionCacheRecord.parentElement == parentElement)
{
// match found, a group exists for this level
controlParentElement = domSelectionCacheRecord.controlParentElement;
continueSearch = NO;
}
else
{
parentIndex++;
if (parentIndex >= commonParentElementsArray.count)
{
continueSearch = NO;
}
}
}
}
if (controlParentElement == NULL)
{
// a controls element was not found, so replicate the DOM path of selected item
NSMutableArray * newParentsArray = [[NSMutableArray alloc] init];
BOOL continueCreatingParents = YES;
if (parentElement == NULL)
{
continueCreatingParents = NO;
}
else
{
NSString * firstParentTagName = parentElement.nodeName;
if ([firstParentTagName isEqualToString:@"svg"] == YES)
{
continueCreatingParents = NO;
}
if ([firstParentTagName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
}
while (continueCreatingParents == YES)
{
NSString * parentTagName = parentElement.nodeName;
DOMElement * newControlParentElement = [domDocument createElementNS:svgNamespace
qualifiedName:parentTagName];
NSString * control_Macsvgid = [parentElement getAttribute:@"macsvgid"];
[newControlParentElement setAttributeNS:NULL qualifiedName:@"control_Macsvgid" value:control_Macsvgid];
[newSelectedRectsGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectionParent"];
[self copyChildAnimationFromDOMElement:parentElement toDOMElement:newControlParentElement offsetPoint:NSZeroPoint];
DOMSelectionCacheRecord * newDOMSelectionCacheRecord =
[[DOMSelectionCacheRecord alloc] init];
newDOMSelectionCacheRecord.parentElement = parentElement;
newDOMSelectionCacheRecord.controlParentElement = newControlParentElement;
[commonParentElementsArray addObject:newDOMSelectionCacheRecord];
[newParentsArray insertObject:newControlParentElement atIndex:0];
if (parentElement.parentNode == NULL)
{
continueCreatingParents = NO;
}
else
{
DOMNode * nextParentNode = parentElement.parentNode;
NSString * nextParentTagName = nextParentNode.nodeName;
if ([nextParentTagName isEqualToString:@"svg"] == YES)
{
continueCreatingParents = NO;
}
else if ([nextParentTagName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
else
{
parentElement = (DOMElement *)nextParentNode;
}
}
}
// inject new elements into DOM from the top down, starting as child of 'newSelectedRectsGroup'
controlParentElement = (DOMElement *)newSelectedRectsGroup;
for (DOMElement * aElement in newParentsArray)
{
[controlParentElement appendChild:aElement];
controlParentElement = (DOMElement *)aElement;
}
}
if (controlParentElement != NULL)
{
// inject blue rectangle around bounds of selected item
if (NSIsEmptyRect(boundingBox) == NO)
{
NSString * selectionStrokeColor = toolSettingsPopoverViewController.selectionStrokeColor;
NSString * selectionStrokeWidth = toolSettingsPopoverViewController.selectionStrokeWidth;
float scaleForDOMElementHandles = [svgWebKitController maxScaleForDOMElementHandles:aSelectedSvgElement];
float selectionStrokeWidthFloat = selectionStrokeWidth.floatValue;
selectionStrokeWidthFloat = selectionStrokeWidthFloat * scaleForDOMElementHandles;
selectionStrokeWidth = [self allocPxString:selectionStrokeWidthFloat];
float bboxX = boundingBox.origin.x - 2;
float bboxY = boundingBox.origin.y - 2;
float bboxWidth = boundingBox.size.width + 4;
float bboxHeight = boundingBox.size.height + 4;
NSString * bboxXString = [self allocPxString:bboxX];
NSString * bboxYString = [self allocPxString:bboxY];
NSString * bboxWidthString = [self allocPxString:bboxWidth];
NSString * bboxHeightString = [self allocPxString:bboxHeight];
DOMElement * selectedItemRectElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"rect" ];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"fill" value:@"none"];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"stroke" value:selectionStrokeColor];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"pointer-events" value:@"none"]; // disallow selection of section rects
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectedRect"];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"x" value:bboxXString];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"y" value:bboxYString];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"width" value:bboxWidthString];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"height" value:bboxHeightString];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"stroke-width" value:selectionStrokeWidth];
NSString * control_Macsvgid = [aSelectedSvgElement getAttribute:@"macsvgid"];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"control_Macsvgid" value:control_Macsvgid];
[controlParentElement appendChild:selectedItemRectElement];
[self copyChildAnimationFromDOMElement:aSelectedSvgElement toDOMElement:selectedItemRectElement offsetPoint:NSZeroPoint];
//NSLog(@"selectionRect added %@, %@, %@, %@", bboxXString, bboxYString, bboxWidthString, bboxHeightString);
}
else
{
//NSLog(@"makeDOMSelectionRects - boundingBox = NULL");
}
}
}
}
// set begin attributes again for animation elements
DOMNodeList * animationElements = [domDocument getElementsByClassName:@"_macsvg_controlAnimation"];
unsigned animationElementsCount = animationElements.length;
for (int i = 0; i < animationElementsCount; i++)
{
DOMElement * controlAnimationElement = (id)[animationElements item:i];
NSString * beginValue = [controlAnimationElement getAttribute:@"begin"];
[controlAnimationElement setAttributeNS:NULL qualifiedName:@"begin" value:beginValue]; // enable animation for element in webkit
}
[self setMacsvgTopGroupChild:newSelectedRectsGroup];
}
//==================================================================================
// makeDOMSelectionHandleAtPoint:macsvgid:handleOwnerElement:handleParentElement:orientation:
//==================================================================================
-(DOMElement *) makeDOMSelectionHandleAtPoint:(NSPoint)handlePoint macsvgid:(NSString *)macsvgid
handleOwnerElement:(DOMElement *)handleOwnerElement
handleParentElement:(DOMElement *)handleParentElement
orientation:(NSString *)orientation
{
float bboxX = handlePoint.x - 3;
float bboxY = handlePoint.y - 3;
float bboxWidth = 7;
float bboxHeight = 7;
NSString * selectionHandleColor = toolSettingsPopoverViewController.selectionHandleColor;
NSString * selectionHandleSize = toolSettingsPopoverViewController.selectionHandleSize;
NSPoint scaleForDOMElementHandles = [svgWebKitController scaleForDOMElementHandles:handleOwnerElement];
float maxHandleScale = scaleForDOMElementHandles.x;
if (scaleForDOMElementHandles.y > maxHandleScale)
{
maxHandleScale = scaleForDOMElementHandles.y;
}
float handleStrokeWidthFloat = 0.0625f * maxHandleScale;
NSString * handleStrokeWidth = [self allocPxString:handleStrokeWidthFloat];
NSMutableString * mutableSelectionHandleSize = [NSMutableString stringWithString:selectionHandleSize];
[mutableSelectionHandleSize replaceOccurrencesOfString:@"px"
withString:@"" options:0 range:NSMakeRange(0, mutableSelectionHandleSize.length)];
float selectionHandleSizeX = mutableSelectionHandleSize.floatValue * scaleForDOMElementHandles.x;
float selectionHandleSizeY = mutableSelectionHandleSize.floatValue * scaleForDOMElementHandles.y;
if (selectionHandleSizeX > 0)
{
bboxX = handlePoint.x - (selectionHandleSizeX / 2.0f);
bboxWidth = selectionHandleSizeX;
}
if (selectionHandleSizeY > 0)
{
bboxY = handlePoint.y - (selectionHandleSizeY / 2.0f);
bboxHeight = selectionHandleSizeY;
}
if ([orientation isEqualToString:@"top"] == YES)
{
bboxY -= 2.0f;
}
else if ([orientation isEqualToString:@"topLeft"] == YES)
{
bboxX -= 2.0f;
bboxY -= 2.0f;
}
else if ([orientation isEqualToString:@"topRight"] == YES)
{
bboxX += 2.0f;
bboxY -= 2.0f;
}
else if ([orientation isEqualToString:@"left"] == YES)
{
bboxX -= 2.0f;
}
else if ([orientation isEqualToString:@"right"] == YES)
{
bboxX += 2.0f;
}
else if ([orientation isEqualToString:@"bottom"] == YES)
{
bboxY += 2.0f;
}
else if ([orientation isEqualToString:@"bottomLeft"] == YES)
{
bboxX -= 2.0f;
bboxY += 2.0f;
}
else if ([orientation isEqualToString:@"bottomRight"] == YES)
{
bboxX += 2.0f;
bboxY += 2.0f;
}
NSString * bboxXString = [self allocPxString:bboxX];
NSString * bboxYString = [self allocPxString:bboxY];
NSString * bboxWidthString = [self allocPxString:bboxWidth];
NSString * bboxHeightString = [self allocPxString:bboxHeight];
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
DOMElement * selectedItemRectElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"rect" ];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"fill" value:selectionHandleColor];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"stroke" value:selectionHandleColor];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"pointer-events" value:@"all"]; // allow selection of handles
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectionHandle"];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"x" value:bboxXString];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"y" value:bboxYString];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"width" value:bboxWidthString];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"height" value:bboxHeightString];
//[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"stroke-width" value:@"0.0625px"];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"stroke-width" value:handleStrokeWidth];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"_macsvg_master_Macsvgid" value:macsvgid];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"_macsvg_handle_orientation" value:orientation];
[handleParentElement appendChild:selectedItemRectElement];
return selectedItemRectElement;
}
//==================================================================================
// makeDOMPluginHandleAtPoint:macsvgid:handleOwnerElement:handleParentElement:handleName:
//==================================================================================
-(DOMElement *) makeDOMPluginHandleAtPoint:(NSPoint)handlePoint macsvgid:(NSString *)macsvgid
handleOwnerElement:(DOMElement *)handleOwnerElement
handleParentElement:(DOMElement *)handleParentElement
handleName:(NSString *)handleName
pluginName:(NSString *)pluginName
{
NSString * pluginHandleStrokeWidth = toolSettingsPopoverViewController.pathEndpointStrokeWidth;
NSString * pluginHandleStrokeColor = toolSettingsPopoverViewController.pathEndpointStrokeColor;
NSString * pluginHandleFillColor = toolSettingsPopoverViewController.pathEndpointFillColor;
NSString * pluginHandleSize = toolSettingsPopoverViewController.pathEndpointRadius;
NSPoint scaleForDOMElementHandles = [svgWebKitController scaleForDOMElementHandles:handleOwnerElement];
float maxHandleScale = scaleForDOMElementHandles.x;
if (scaleForDOMElementHandles.y > maxHandleScale)
{
maxHandleScale = scaleForDOMElementHandles.y;
}
float handleStrokeWidthFloat = pluginHandleStrokeWidth.floatValue * maxHandleScale;
NSString * handleStrokeWidth = [self allocPxString:handleStrokeWidthFloat];
NSMutableString * mutablePluginHandleSize = [NSMutableString stringWithString:pluginHandleSize];
[mutablePluginHandleSize replaceOccurrencesOfString:@"px"
withString:@"" options:0 range:NSMakeRange(0, mutablePluginHandleSize.length)];
//float pluginHandleSizeX = mutablePluginHandleSize.floatValue * scaleForDOMElementHandles.x;
//float pluginHandleSizeY = mutablePluginHandleSize.floatValue * scaleForDOMElementHandles.y;
NSString * xString = [self allocPxString:handlePoint.x];
NSString * yString = [self allocPxString:handlePoint.y];
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
NSString * pointRadiusString = toolSettingsPopoverViewController.pathEndpointRadius;
float pointRadius = pointRadiusString.floatValue;
//pointRadius *= 2.0f;
pointRadius *= maxHandleScale;
pointRadiusString = [NSString stringWithFormat:@"%f", pointRadius];
DOMElement * selectedItemRectElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"circle" ];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"fill" value:pluginHandleFillColor];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"stroke" value:pluginHandleStrokeColor];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"pointer-events" value:@"all"]; // allow selection of handles
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectionHandle"];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"cx" value:xString];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"cy" value:yString];
//[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"stroke-width" value:@"0.0625px"];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"r" value:pointRadiusString];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"stroke-width" value:handleStrokeWidth];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"_macsvg_master_Macsvgid" value:macsvgid];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"_macsvg_handle_orientation" value:@"plugin"];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"_macsvg_handle_name" value:handleName];
[selectedItemRectElement setAttributeNS:NULL qualifiedName:@"_macsvg_handle_plugin" value:pluginName];
[handleParentElement appendChild:selectedItemRectElement];
return selectedItemRectElement;
}
//==================================================================================
// makeDOMSelectionHandles
//==================================================================================
-(void) makeDOMSelectionHandles:(DOMElement *)aDomElement
{
//NSLog(@"enter makeDOMSelectionHandles");
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
//DOMNodeList * svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
//DOMNode * svgElementNode = [svgElementsList item:0];
//DOMElement * svgElement = (DOMElement *)svgElementNode;
DOMElement * svgElement = domDocument.documentElement;
if ([svgElement isKindOfClass:[DOMHTMLElement class]] == YES)
{
// this is an XHTML element - search for an SVG element inside
DOMNodeList * svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
if (svgElementsList.length > 0)
{
svgElement = (DOMElement *)[svgElementsList item:0];
}
else
{
svgElement = NULL;
}
}
if (svgElement != NULL)
{
DOMNode * svgElementNode = (DOMNode *)svgElement;
[self removeMacsvgTopGroupChildByID:@"_macsvg_selectionHandlesGroup"];
self.domElementForHandles = NULL;
self.domElementForHandlesCreationTime = 0;
NSString * key_Macsvgid = [aDomElement getAttribute:@"macsvgid"];
DOMElement * newSelectionHandlesGroup = [domDocument createElementNS:svgNamespace
qualifiedName:@"g"];
[newSelectionHandlesGroup setAttributeNS:NULL qualifiedName:@"id" value:@"_macsvg_selectionHandlesGroup"];
[newSelectionHandlesGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectionHandlesGroup"];
[newSelectionHandlesGroup setAttributeNS:NULL qualifiedName:@"key_Macsvgid" value:key_Macsvgid];
// inject new selectionHandlesGroup into DOM
//[svgElement appendChild:newSelectionHandlesGroup]; // test 20160904 - moved to end
DOMElement * handleParentElement = NULL;
if (aDomElement != NULL)
{
NSString * elementName = aDomElement.nodeName;
NSString * validSVGLocatableName = (self.validElementsForTransformDictionary)[elementName];
if (validSVGLocatableName != NULL)
{
//DOMElement * parentElement = (id)[aDomElement parentNode];
//DOMElement * parentElement = aDomElement; // 20160703
DOMElement * parentElement = aDomElement.parentElement; // 20160703
// replicate the DOM path of selected item
NSMutableArray * newParentsArray = [[NSMutableArray alloc] init];
// for partial transforms, when editing a transform attribute which contains multiple operations
DOMElement * intermediateTransformGroupElement = [domDocument createElementNS:svgNamespace qualifiedName:@"g"];
[intermediateTransformGroupElement setAttributeNS:NULL qualifiedName:@"id" value:@"_macsvg_path_transform_intermediate"];
[intermediateTransformGroupElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_path_transform_intermediate"];
[intermediateTransformGroupElement setAttributeNS:NULL qualifiedName:@"transform" value:@""];
[newParentsArray insertObject:intermediateTransformGroupElement atIndex:0];
BOOL continueCreatingParents = YES;
if (parentElement == NULL)
{
continueCreatingParents = NO;
}
else
{
NSString * firstParentTagName = parentElement.nodeName;
if ([firstParentTagName isEqualToString:@"svg"] == YES)
{
continueCreatingParents = NO;
}
if ([firstParentTagName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
}
// create parent group elements to match parent groups and transforms for selected element, working back from current element to document root
while (continueCreatingParents == YES)
{
NSString * parentTagName = parentElement.nodeName;
if (parentElement == aDomElement)
{
parentTagName = @"g";
}
DOMElement * newHandleParentElement = [domDocument createElementNS:svgNamespace
qualifiedName:parentTagName];
NSString * parent_Macsvgid = [parentElement getAttribute:@"macsvgid"];
[newHandleParentElement setAttributeNS:NULL qualifiedName:@"_macsvg_master_Macsvgid" value:parent_Macsvgid];
[newSelectionHandlesGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectionHandlesParent"];
[self copyChildAnimationFromDOMElement:parentElement toDOMElement:newHandleParentElement offsetPoint:NSZeroPoint];
[newParentsArray insertObject:newHandleParentElement atIndex:0];
if (parentElement.parentNode == NULL)
{
continueCreatingParents = NO;
}
else
{
DOMNode * nextParentNode = parentElement.parentNode;
if (nextParentNode == svgElementNode)
{
continueCreatingParents = NO;
}
else if ([nextParentNode.nodeName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
else
{
parentElement = (id)nextParentNode;
}
}
}
// inject new elements into DOM from the top down, starting as child of 'newSelectionHandlesGroup'
handleParentElement = (id)newSelectionHandlesGroup;
for (DOMElement * aElement in newParentsArray)
{
[handleParentElement appendChild:aElement];
handleParentElement = (id)aElement;
}
//}
MacSVGAppDelegate * macSVGAppDelegate = (MacSVGAppDelegate *)NSApp.delegate;
WebKitInterface * webKitInterface = [macSVGAppDelegate webKitInterface];
NSRect boundingBox = [webKitInterface bBoxForDOMElement:aDomElement];
//boundingBox = [webKitInterface bBoxForDOMElement:aSelectedSvgElement globalContext:[[svgWebView mainFrame] globalContext]];
if ([aDomElement.nodeName isEqualToString:@"use"])
{
NSString * xAttributeString = [aDomElement getAttribute:@"x"];
NSString * yAttributeString = [aDomElement getAttribute:@"y"];
float xAttributeFloat = xAttributeString.floatValue;
float yAttributeFloat = yAttributeString.floatValue;
boundingBox.origin.x += xAttributeFloat;
boundingBox.origin.y += yAttributeFloat;
}
if ([aDomElement.nodeName isEqualToString:@"foreignObject"])
{
NSString * xAttributeString = [aDomElement getAttribute:@"x"];
NSString * yAttributeString = [aDomElement getAttribute:@"y"];
NSString * widthAttributeString = [aDomElement getAttribute:@"width"];
NSString * heightAttributeString = [aDomElement getAttribute:@"height"];
float xAttributeFloat = xAttributeString.floatValue;
float yAttributeFloat = yAttributeString.floatValue;
float widthAttributeFloat = widthAttributeString.floatValue;
float heightAttributeFloat = heightAttributeString.floatValue;
boundingBox.origin.x = xAttributeFloat;
boundingBox.origin.y = yAttributeFloat;
boundingBox.size.width = widthAttributeFloat;
boundingBox.size.height = heightAttributeFloat;
}
if (NSIsEmptyRect(boundingBox) == NO)
{
NSString * macsvgid = [aDomElement getAttribute:@"macsvgid"];
if (macsvgid == NULL)
{
NSLog(@"makeDOMSelectionHandles - macsvgid = NULL");
}
else
{
if ([macsvgid isEqualToString:@""] == YES)
{
NSLog(@"makeDOMSelectionHandles - macsvgid empty");
}
}
/*
// 20161017 - tentatively disable copying the transform attribute here - it was getting applied twice in the new controls elements
NSString * transformAttribute = [aDomElement getAttribute:@"transform"];
if (transformAttribute != NULL)
{
if (transformAttribute.length > 0)
{
[handleParentElement setAttributeNS:NULL qualifiedName:@"transform" value:transformAttribute];
}
}
*/
NSString * elementName = aDomElement.nodeName;
if ((self.validElementsForTransformDictionary)[elementName] != NULL)
{
NSPoint handlePoint = NSZeroPoint;
handlePoint.x = boundingBox.origin.x;
handlePoint.y = boundingBox.origin.y;
DOMElement * topLeftHandle = [self makeDOMSelectionHandleAtPoint:handlePoint macsvgid:macsvgid
handleOwnerElement:aDomElement
handleParentElement:handleParentElement orientation:@"topLeft"];
NSPoint topLeftOffsetPoint = NSMakePoint(-2.0f, 0.0f);
[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:topLeftHandle offsetPoint:topLeftOffsetPoint];
handlePoint.x = boundingBox.origin.x + boundingBox.size.width;
handlePoint.y = boundingBox.origin.y;
DOMElement * topRightHandle = [self makeDOMSelectionHandleAtPoint:handlePoint macsvgid:macsvgid
handleOwnerElement:aDomElement
handleParentElement:handleParentElement orientation:@"topRight"];
NSPoint topRightOffsetPoint = NSMakePoint(boundingBox.size.width, 0.0f);
[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:topRightHandle offsetPoint:topRightOffsetPoint];
handlePoint.x = boundingBox.origin.x;
handlePoint.y = boundingBox.origin.y + boundingBox.size.height;
DOMElement * bottomLeftHandle = [self makeDOMSelectionHandleAtPoint:handlePoint macsvgid:macsvgid
handleOwnerElement:aDomElement
handleParentElement:handleParentElement orientation:@"bottomLeft"];
NSPoint bottomLeftOffsetPoint = NSMakePoint(-2.0f, boundingBox.size.height);
[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:bottomLeftHandle offsetPoint:bottomLeftOffsetPoint];
handlePoint.x = boundingBox.origin.x + boundingBox.size.width;
handlePoint.y = boundingBox.origin.y + boundingBox.size.height;
DOMElement * bottomRightHandle = [self makeDOMSelectionHandleAtPoint:handlePoint macsvgid:macsvgid
handleOwnerElement:aDomElement
handleParentElement:handleParentElement orientation:@"bottomRight"];
NSPoint bottomRightOffsetPoint = NSMakePoint(boundingBox.size.width, boundingBox.size.height);
[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:bottomRightHandle offsetPoint:bottomRightOffsetPoint];
handlePoint.x = boundingBox.origin.x + (boundingBox.size.width / 2.0f);
handlePoint.y = boundingBox.origin.y;
DOMElement * topHandle = [self makeDOMSelectionHandleAtPoint:handlePoint macsvgid:macsvgid
handleOwnerElement:aDomElement
handleParentElement:handleParentElement orientation:@"top"];
NSPoint topOffsetPoint = NSMakePoint(boundingBox.size.width / 2.0f, 0.0f);
[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:topHandle offsetPoint:topOffsetPoint];
handlePoint.x = boundingBox.origin.x;
handlePoint.y = boundingBox.origin.y + (boundingBox.size.height / 2.0f);
DOMElement * leftHandle = [self makeDOMSelectionHandleAtPoint:handlePoint macsvgid:macsvgid
handleOwnerElement:aDomElement
handleParentElement:handleParentElement orientation:@"left"];
NSPoint leftOffsetPoint = NSMakePoint(-2.0f, boundingBox.size.height / 2.0f);
[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:leftHandle offsetPoint:leftOffsetPoint];
handlePoint.x = boundingBox.origin.x + (boundingBox.size.width / 2.0f);
handlePoint.y = boundingBox.origin.y + boundingBox.size.height;
DOMElement * bottomHandle = [self makeDOMSelectionHandleAtPoint:handlePoint macsvgid:macsvgid
handleOwnerElement:aDomElement
handleParentElement:handleParentElement orientation:@"bottom"];
NSPoint bottomOffsetPoint = NSMakePoint(boundingBox.size.width / 2.0f, boundingBox.size.height);
[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:bottomHandle offsetPoint:bottomOffsetPoint];
handlePoint.x = boundingBox.origin.x + boundingBox.size.width;
handlePoint.y = boundingBox.origin.y + (boundingBox.size.height / 2.0f);
DOMElement * rightHandle = [self makeDOMSelectionHandleAtPoint:handlePoint macsvgid:macsvgid
handleOwnerElement:aDomElement
handleParentElement:handleParentElement orientation:@"right"];
NSPoint rightOffsetPoint = NSMakePoint(boundingBox.size.width, boundingBox.size.height / 2.0f);
[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:rightHandle offsetPoint:rightOffsetPoint];
//[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:handleParentElement];
self.domElementForHandles = aDomElement;
self.domElementForHandlesCreationTime = time(NULL);
}
}
}
}
else
{
//NSLog(@"makeDOMSelectionHandles aDomElement is NULL");
}
//[self addPluginSelectionHandlesWithDOMElement:aDomElement handlesGroup:newSelectionHandlesGroup];
if (handleParentElement != NULL)
{
[self addPluginSelectionHandlesWithDOMElement:aDomElement handlesGroup:handleParentElement];
}
// inject new selectionHandlesGroup into DOM
//[svgElement appendChild:newSelectionHandlesGroup]; // test 20160904 - moved to end
[self setMacsvgTopGroupChild:newSelectionHandlesGroup];
}
}
//==================================================================================
// addPluginSelectionHandlesWithDOMElement:handlesGroup:
//==================================================================================
-(void) addPluginSelectionHandlesWithDOMElement:(DOMElement *)aDomElement
handlesGroup:(DOMElement *)newSelectionHandlesGroup
{
MacSVGPlugin * currentPlugin = [macSVGDocumentWindowController.editorUIFrameController currentPlugin];
if (currentPlugin != NULL)
{
[currentPlugin addPluginSelectionHandlesWithDOMElement:aDomElement handlesGroup:newSelectionHandlesGroup];
}
}
//==================================================================================
// addPluginSelectionHandleWithDOMElement:handlesGroup:x:y:handleName:
//==================================================================================
- (void)addPluginSelectionHandleWithDOMElement:(DOMElement *)aDomElement
handlesGroup:(DOMElement *)newSelectionHandlesGroup
x:(float)x y:(float)y handleName:(NSString *)handleName
pluginName:(NSString *)pluginName
{
// for use in callback from plug-in, e.g. for center-of-rotation in transform attribute editor
NSPoint handlePoint = NSMakePoint(x, y);
NSString * macsvgid = [aDomElement getAttribute:@"macsvgid"];
DOMElement * aPluginEditorHandle = [self makeDOMPluginHandleAtPoint:handlePoint macsvgid:macsvgid
handleOwnerElement:aDomElement handleParentElement:newSelectionHandlesGroup handleName:handleName
pluginName:pluginName];
//NSPoint offsetPoint = NSMakePoint(-2.0f, 0.0f);
NSPoint offsetPoint = NSMakePoint(0.0f, 0.0f);
[self copyChildAnimationFromDOMElement:aDomElement toDOMElement:aPluginEditorHandle offsetPoint:offsetPoint];
[newSelectionHandlesGroup appendChild:aPluginEditorHandle];
}
//==================================================================================
// removeDOMPathSegmentHighlight:
//==================================================================================
-(void) removeDOMPathSegmentHighlight
{
[self removeMacsvgTopGroupChildByID:@"_macsvg_highlightPathSegmentGroup"];
[self removeMacsvgTopGroupChildByID:@"_macsvg_highlightPathSegmentMarker"];
//svgWebKitController.domMouseEventsController.svgPathEditor.pathSegmentIndex = -1;
}
//==================================================================================
// removeDOMPolylinePointHighlight:
//==================================================================================
-(void) removeDOMPolylinePointHighlight
{
[self removeMacsvgTopGroupChildByID:@"_macsvg_highlightPolylinePointGroup"];
//svgWebKitController.domMouseEventsController.svgPolylineEditor.polylinePointIndex = -1;
}
//==================================================================================
// removeDOMLinePointHighlight:
//==================================================================================
-(void) removeDOMLinePointHighlight
{
[self removeMacsvgTopGroupChildByID:@"_macsvg_highlightLinePointGroup"];
//svgWebKitController.domMouseEventsController.svgLineEditor.linePointIndex = -1;
}
//==================================================================================
// highlightPolylinePoint
//==================================================================================
- (IBAction)highlightPolylinePoint
{
NSUInteger selectedItemsCount = [svgXMLDOMSelectionManager.selectedElementsManager selectedElementsCount];
if (selectedItemsCount == 1)
{
NSXMLElement * selectedXMLElement =
[svgXMLDOMSelectionManager.selectedElementsManager xmlElementAtIndex:0];
DOMElement * selectedDOMElement =
[svgXMLDOMSelectionManager.selectedElementsManager domElementAtIndex:0];
NSString * selectedXMLElementName = selectedXMLElement.name;
BOOL validPolyline = NO;
if ([selectedXMLElementName isEqualToString:@"polyline"] == YES)
{
validPolyline = YES;
}
else if ([selectedXMLElementName isEqualToString:@"polygon"] == YES)
{
validPolyline = YES;
}
if (validPolyline == YES)
{
if (svgWebKitController.domMouseEventsController.svgPolylineEditor.polylinePointIndex >= 0)
{
NSString * pointsString = [selectedDOMElement getAttribute:@"points"];
NSMutableArray * polylinePointsArray = [svgWebKitController.domMouseEventsController.svgPolylineEditor buildPolylinePointsArrayWithPointsString:pointsString];
if (svgWebKitController.domMouseEventsController.svgPolylineEditor.polylinePointIndex < polylinePointsArray.count)
{
NSMutableDictionary * polylinePointDictionary = polylinePointsArray[svgWebKitController.domMouseEventsController.svgPolylineEditor.polylinePointIndex];
NSString * xString = polylinePointDictionary[@"x"];
NSString * yString = polylinePointDictionary[@"y"];
float xFloat = xString.floatValue;
float yFloat = yString.floatValue;
NSPoint polylinePoint = NSMakePoint(xFloat, yFloat);
[self highlightPolylinePointInDOM:polylinePoint forDOMElement:selectedDOMElement];
}
else
{
svgWebKitController.domMouseEventsController.svgPolylineEditor.polylinePointIndex = -1; // index was invalid
}
}
}
}
}
//==================================================================================
// highlightPolylinePointInDOM:forDOMElement:
//==================================================================================
-(void) highlightPolylinePointInDOM:(NSPoint)polylinePoint forDOMElement:(DOMElement *)polylineDOMElement
{
// pathSegmentString is basically a moveto, and a cubic curve
NSString * selectionHandleColor = self.segmentStrokeHexColor;
float scaleForDOMElementHandles = [svgWebKitController maxScaleForDOMElementHandles:polylineDOMElement];
float scaledStrokeWidthFloat = self.segmentStrokeWidth * scaleForDOMElementHandles;
NSString * selectionStrokeWidth = [self allocPxString:scaledStrokeWidthFloat];
if (self.segmentStrokeWidth == 0)
{
NSString * selectionStrokeWidthString = toolSettingsPopoverViewController.selectionStrokeWidth;
scaledStrokeWidthFloat = selectionStrokeWidthString.floatValue;
scaledStrokeWidthFloat *= scaleForDOMElementHandles;
selectionStrokeWidth = [self allocPxString:scaledStrokeWidthFloat];
}
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
DOMElement * topSvgElement = [self macsvgTopGroupElement];
[self removeDOMPolylinePointHighlight];
if (topSvgElement == NULL)
{
DOMNodeList * svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
if (svgElementsList.length == 0)
{
DOMElement * newSvgElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"svg"];
DOMElement * documentElement = domDocument.documentElement;
int clientLeft = documentElement.clientLeft;
int clientTop = documentElement.clientTop;
int clientWidth = documentElement.clientWidth;
int clientHeight = documentElement.clientHeight;
NSString * svgWidth = [NSString stringWithFormat:@"%dpx", clientWidth];
NSString * svgHeight = [NSString stringWithFormat:@"%dpx", clientHeight];
NSString * svgViewBox = [NSString stringWithFormat:@"%d %d %d %d", clientLeft, clientTop, clientWidth, clientHeight];
[newSvgElement setAttribute:@"xmlns" value:@"http://www.w3.org/2000/svg"];
[newSvgElement setAttribute:@"xmlns:xlink" value:@"http://www.w3.org/1999/xlink"];
[newSvgElement setAttribute:@"cursor" value:@"crosshair"];
[newSvgElement setAttribute:@"height" value:svgHeight];
[newSvgElement setAttribute:@"id" value:@"svg_document"];
[newSvgElement setAttribute:@"width" value:svgWidth];
[newSvgElement setAttribute:@"version" value:@"1.1"];
[newSvgElement setAttribute:@"preserveAspectRatio" value:@"xMidYMid meet"];
[newSvgElement setAttribute:@"viewBox" value:svgViewBox];
[documentElement appendChild:newSvgElement];
svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
}
DOMNode * svgElementNode = [svgElementsList item:0];
topSvgElement = (DOMElement *)svgElementNode;
}
DOMElement * newHighlightPolylinePointGroup = [domDocument createElementNS:svgNamespace
qualifiedName:@"g"];
[newHighlightPolylinePointGroup setAttributeNS:NULL qualifiedName:@"id" value:@"_macsvg_highlightPolylinePointGroup"];
[newHighlightPolylinePointGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_highlightPolylinePointGroup"];
// inject new newHighlightPathSegmentGroup into DOM
[topSvgElement appendChild:newHighlightPolylinePointGroup];
NSString * elementName = polylineDOMElement.nodeName;
if ((self.validElementsForTransformDictionary)[elementName] != NULL)
{
DOMElement * parentElement = (id)polylineDOMElement.parentNode;
DOMElement * controlParentElement = NULL;
if (controlParentElement == NULL)
{
// replicate the segment of the DOM path
NSMutableArray * newParentsArray = [[NSMutableArray alloc] init];
BOOL continueCreatingParents = YES;
if (parentElement == NULL)
{
continueCreatingParents = NO;
}
else
{
NSString * firstParentTagName = parentElement.nodeName;
if ([firstParentTagName isEqualToString:@"svg"] == YES)
{
continueCreatingParents = NO;
}
if ([firstParentTagName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
}
while (continueCreatingParents == YES)
{
NSString * parentTagName = parentElement.nodeName;
DOMElement * newControlParentElement = [domDocument createElementNS:svgNamespace
qualifiedName:parentTagName];
NSString * control_Macsvgid = [parentElement getAttribute:@"macsvgid"];
[newControlParentElement setAttributeNS:NULL qualifiedName:@"control_Macsvgid" value:control_Macsvgid];
[newHighlightPolylinePointGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectionParent"];
[self copyChildAnimationFromDOMElement:parentElement toDOMElement:newControlParentElement offsetPoint:NSZeroPoint];
DOMSelectionCacheRecord * newDOMSelectionCacheRecord =
[[DOMSelectionCacheRecord alloc] init];
newDOMSelectionCacheRecord.parentElement = parentElement;
newDOMSelectionCacheRecord.controlParentElement = newControlParentElement;
[newParentsArray insertObject:newControlParentElement atIndex:0];
if (parentElement.parentNode == NULL)
{
continueCreatingParents = NO;
}
else
{
DOMNode * nextParentNode = parentElement.parentNode;
NSString * nextParentTagName = nextParentNode.nodeName;
if ([nextParentTagName isEqualToString:@"svg"] == YES)
{
continueCreatingParents = NO;
}
if ([nextParentTagName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
else
{
parentElement = (DOMElement *)nextParentNode;
}
}
}
// inject new elements into DOM from the top down, starting as child of 'newSelectedRectsGroup'
controlParentElement = (DOMElement *)newHighlightPolylinePointGroup;
for (DOMElement * aElement in newParentsArray)
{
[controlParentElement appendChild:aElement];
controlParentElement = (DOMElement *)aElement;
}
}
if (controlParentElement != NULL)
{
// highlight the point
NSString * pathWidthString = [polylineDOMElement getAttribute:@"stroke-width"];
float pathWidth = pathWidthString.integerValue;
if (pathWidth > 0)
{
pathWidth += 2;
selectionStrokeWidth = [NSString stringWithFormat:@"%f", pathWidth];
}
NSString * xString = [self allocPxString:polylinePoint.x];
NSString * yString = [self allocPxString:polylinePoint.y];
DOMElement * pointHandleCircleElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"circle" ];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"pointer-events" value:@"none"]; // disallow selection
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"cx" value:xString];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"cy" value:yString];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_highlight_polyline_point"];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"fill"
value:@"none"];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"stroke" value:selectionHandleColor];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"stroke-width" value:selectionStrokeWidth];
NSString * pointRadiusString = toolSettingsPopoverViewController.pathEndpointRadius;
float pointRadius = pointRadiusString.floatValue;
pointRadius *= 2.0f;
pointRadiusString = [self allocPxString:pointRadius];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"r"
value:pointRadiusString];
//[polylinePointHandlesGroup appendChild:pointHandleCircleElement];
[controlParentElement appendChild:pointHandleCircleElement];
[self copyChildAnimationFromDOMElement:polylineDOMElement toDOMElement:pointHandleCircleElement offsetPoint:NSZeroPoint];
/*
DOMElement * polylineElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"polyline" ];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"fill" value:@"none"];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"stroke" value:selectionHandleColor];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"pointer-events" value:@"none"]; // disallow selection of section rects
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_highlight_path"];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"stroke-width" value:selectionStrokeWidth];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"points" value:polylinePointsString];
NSString * control_Macsvgid = [polylineDOMElement getAttribute:@"macsvgid"];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"control_Macsvgid" value:control_Macsvgid];
[controlParentElement appendChild:pathSegmentElement];
[self copyChildAnimationFromDOMElement:polylineDOMElement toDOMElement:pathSegmentElement];
*/
//NSLog(@"selectionRect added %@, %@, %@, %@", bboxXString, bboxYString, bboxWidthString, bboxHeightString);
}
}
// set begin attributes again for animation elements
DOMNodeList * animationElements = [domDocument getElementsByClassName:@"_macsvg_controlAnimation"];
unsigned animationElementsCount = animationElements.length;
for (int i = 0; i < animationElementsCount; i++)
{
DOMElement * controlAnimationElement = (id)[animationElements item:i];
NSString * beginValue = [controlAnimationElement getAttribute:@"begin"];
[controlAnimationElement setAttributeNS:NULL qualifiedName:@"begin" value:beginValue]; // enable animation for element in webkit
}
}
//==================================================================================
// highlightLinePointInDOM:forDOMElement:
//==================================================================================
- (IBAction)highlightLinePoint
{
NSUInteger selectedItemsCount = [svgXMLDOMSelectionManager.selectedElementsManager selectedElementsCount];
if (selectedItemsCount == 1)
{
NSXMLElement * selectedXMLElement =
[svgXMLDOMSelectionManager.selectedElementsManager xmlElementAtIndex:0];
DOMElement * selectedDOMElement =
[svgXMLDOMSelectionManager.selectedElementsManager domElementAtIndex:0];
NSString * selectedXMLElementName = selectedXMLElement.name;
BOOL validLine = NO;
if ([selectedXMLElementName isEqualToString:@"line"] == YES)
{
validLine = YES;
}
if (validLine == YES)
{
if (svgWebKitController.domMouseEventsController.svgLineEditor.linePointIndex >= 0)
{
NSString * xString = [selectedDOMElement getAttribute:@"x1"];
NSString * yString = [selectedDOMElement getAttribute:@"y1"];
if (svgWebKitController.domMouseEventsController.svgLineEditor.linePointIndex > 0)
{
xString = [selectedDOMElement getAttribute:@"x2"];
yString = [selectedDOMElement getAttribute:@"y2"];
}
float xFloat = xString.floatValue;
float yFloat = yString.floatValue;
NSPoint linePoint = NSMakePoint(xFloat, yFloat);
[self highlightLinePointInDOM:linePoint forDOMElement:selectedDOMElement];
}
}
}
}
//==================================================================================
// highlightLinePointInDOM:forDOMElement:
//==================================================================================
-(void) highlightLinePointInDOM:(NSPoint)linePoint forDOMElement:(DOMElement *)lineDOMElement
{
NSString * selectionHandleColor = self.segmentStrokeHexColor;
float scaleForDOMElementHandles = [svgWebKitController maxScaleForDOMElementHandles:lineDOMElement];
float scaledStrokeWidthFloat = self.segmentStrokeWidth * scaleForDOMElementHandles;
NSString * selectionStrokeWidth = [self allocPxString:scaledStrokeWidthFloat];
if (self.segmentStrokeWidth == 0)
{
NSString * selectionStrokeWidthString = toolSettingsPopoverViewController.selectionStrokeWidth;
scaledStrokeWidthFloat = selectionStrokeWidthString.floatValue;
scaledStrokeWidthFloat *= scaleForDOMElementHandles;
selectionStrokeWidth = [self allocPxString:scaledStrokeWidthFloat];
}
[self removeDOMLinePointHighlight];
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
DOMElement * topSvgElement = [self macsvgTopGroupElement];
if (topSvgElement == NULL)
{
DOMNodeList * svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
if (svgElementsList.length == 0)
{
DOMElement * newSvgElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"svg"];
DOMElement * documentElement = domDocument.documentElement;
int clientLeft = documentElement.clientLeft;
int clientTop = documentElement.clientTop;
int clientWidth = documentElement.clientWidth;
int clientHeight = documentElement.clientHeight;
NSString * svgWidth = [NSString stringWithFormat:@"%dpx", clientWidth];
NSString * svgHeight = [NSString stringWithFormat:@"%dpx", clientHeight];
NSString * svgViewBox = [NSString stringWithFormat:@"%d %d %d %d", clientLeft, clientTop, clientWidth, clientHeight];
[newSvgElement setAttribute:@"xmlns" value:@"http://www.w3.org/2000/svg"];
[newSvgElement setAttribute:@"xmlns:xlink" value:@"http://www.w3.org/1999/xlink"];
[newSvgElement setAttribute:@"cursor" value:@"crosshair"];
[newSvgElement setAttribute:@"height" value:svgHeight];
[newSvgElement setAttribute:@"id" value:@"svg_document"];
[newSvgElement setAttribute:@"width" value:svgWidth];
[newSvgElement setAttribute:@"version" value:@"1.1"];
[newSvgElement setAttribute:@"preserveAspectRatio" value:@"xMidYMid meet"];
[newSvgElement setAttribute:@"viewBox" value:svgViewBox];
[documentElement appendChild:newSvgElement];
svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
}
DOMNode * svgElementNode = [svgElementsList item:0];
topSvgElement = (DOMElement *)svgElementNode;
}
DOMElement * newHighlightLinePointGroup = [domDocument createElementNS:svgNamespace
qualifiedName:@"g"];
[newHighlightLinePointGroup setAttributeNS:NULL qualifiedName:@"id" value:@"_macsvg_highlightLinePointGroup"];
[newHighlightLinePointGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_highlightLinePointGroup"];
// inject new newHighlightPathSegmentGroup into DOM
[topSvgElement appendChild:newHighlightLinePointGroup];
NSString * elementName = lineDOMElement.nodeName;
if ((self.validElementsForTransformDictionary)[elementName] != NULL)
{
DOMElement * parentElement = (id)lineDOMElement.parentNode;
DOMElement * controlParentElement = NULL;
if (controlParentElement == NULL)
{
// replicate the segment of the DOM path
NSMutableArray * newParentsArray = [[NSMutableArray alloc] init];
BOOL continueCreatingParents = YES;
if (parentElement == NULL)
{
continueCreatingParents = NO;
}
else
{
NSString * firstParentTagName = parentElement.nodeName;
if ([firstParentTagName isEqualToString:@"svg"] == YES)
{
continueCreatingParents = NO;
}
if ([firstParentTagName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
}
while (continueCreatingParents == YES)
{
NSString * parentTagName = parentElement.nodeName;
DOMElement * newControlsParentElement = [domDocument createElementNS:svgNamespace
qualifiedName:parentTagName];
NSString * control_Macsvgid = [parentElement getAttribute:@"macsvgid"];
[newControlsParentElement setAttributeNS:NULL qualifiedName:@"control_Macsvgid" value:control_Macsvgid];
[newHighlightLinePointGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectionParent"];
[self copyChildAnimationFromDOMElement:parentElement toDOMElement:newControlsParentElement offsetPoint:NSZeroPoint];
DOMSelectionCacheRecord * newDOMSelectionCacheRecord =
[[DOMSelectionCacheRecord alloc] init];
newDOMSelectionCacheRecord.parentElement = parentElement;
newDOMSelectionCacheRecord.controlParentElement = newControlsParentElement;
[newParentsArray insertObject:newControlsParentElement atIndex:0];
if (parentElement.parentNode == NULL)
{
continueCreatingParents = NO;
}
else
{
DOMNode * nextParentNode = parentElement.parentNode;
NSString * nextParentTagName = nextParentNode.nodeName;
if ([nextParentTagName isEqualToString:@"svg"] == YES)
{
continueCreatingParents = NO;
}
if ([nextParentTagName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
else
{
parentElement = (DOMElement *)nextParentNode;
}
}
}
// inject new elements into DOM from the top down, starting as child of 'newSelectedRectsGroup'
controlParentElement = (DOMElement *)newHighlightLinePointGroup;
for (DOMElement * aElement in newParentsArray)
{
[controlParentElement appendChild:aElement];
controlParentElement = (DOMElement *)aElement;
}
}
if (controlParentElement != NULL)
{
// highlight the point
NSString * pathWidthString = [lineDOMElement getAttribute:@"stroke-width"];
float pathWidth = pathWidthString.integerValue;
if (pathWidth > 0)
{
pathWidth += 2;
selectionStrokeWidth = [NSString stringWithFormat:@"%f", pathWidth];
}
NSString * xString = [self allocPxString:linePoint.x];
NSString * yString = [self allocPxString:linePoint.y];
DOMElement * pointHandleCircleElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"circle" ];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"pointer-events" value:@"none"]; // disallow selection
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"cx" value:xString];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"cy" value:yString];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_highlight_polyline_point"];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"fill"
value:@"none"];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"stroke" value:selectionHandleColor];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"stroke-width" value:selectionStrokeWidth];
NSString * pointRadiusString = toolSettingsPopoverViewController.pathEndpointRadius;
float pointRadius = pointRadiusString.floatValue;
pointRadius *= 2.0f;
pointRadiusString = [self allocPxString:pointRadius];
[pointHandleCircleElement setAttributeNS:NULL qualifiedName:@"r"
value:pointRadiusString];
[controlParentElement appendChild:pointHandleCircleElement];
[self copyChildAnimationFromDOMElement:lineDOMElement toDOMElement:pointHandleCircleElement offsetPoint:NSZeroPoint];
}
}
// set begin attributes again for animation elements
DOMNodeList * animationElements = [domDocument getElementsByClassName:@"_macsvg_controlAnimation"];
unsigned animationElementsCount = animationElements.length;
for (int i = 0; i < animationElementsCount; i++)
{
DOMElement * controlAnimationElement = (id)[animationElements item:i];
NSString * beginValue = [controlAnimationElement getAttribute:@"begin"];
[controlAnimationElement setAttributeNS:NULL qualifiedName:@"begin" value:beginValue]; // enable animation for element in webkit
}
}
//==================================================================================
// highlightPathSegmentInDOM:forDOMElement:
//==================================================================================
-(void) highlightPathSegmentInDOM:(NSString *)pathSegmentString forDOMElement:(DOMElement *)pathDOMElement
{
// pathSegmentString is basically a moveto, and a cubic curve
NSString * selectionHandleColor = self.segmentStrokeHexColor;
float scaleForDOMElementHandles = [svgWebKitController maxScaleForDOMElementHandles:pathDOMElement];
float scaledStrokeWidthFloat = self.segmentStrokeWidth * scaleForDOMElementHandles;
NSString * selectionStrokeWidth = [self allocPxString:scaledStrokeWidthFloat];
if (self.segmentStrokeWidth == 0)
{
NSString * selectionStrokeWidthString = toolSettingsPopoverViewController.selectionStrokeWidth;
scaledStrokeWidthFloat = selectionStrokeWidthString.floatValue;
scaledStrokeWidthFloat *= scaleForDOMElementHandles;
selectionStrokeWidth = [self allocPxString:scaledStrokeWidthFloat];
}
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
DOMElement * topSvgElement = [self macsvgTopGroupElement];
[self removeDOMPathSegmentHighlight];
if (topSvgElement == NULL)
{
DOMNodeList * svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
if (svgElementsList.length == 0)
{
DOMElement * newSvgElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"svg"];
DOMElement * documentElement = domDocument.documentElement;
int clientLeft = documentElement.clientLeft;
int clientTop = documentElement.clientTop;
int clientWidth = documentElement.clientWidth;
int clientHeight = documentElement.clientHeight;
NSString * svgWidth = [NSString stringWithFormat:@"%dpx", clientWidth];
NSString * svgHeight = [NSString stringWithFormat:@"%dpx", clientHeight];
NSString * svgViewBox = [NSString stringWithFormat:@"%d %d %d %d", clientLeft, clientTop, clientWidth, clientHeight];
[newSvgElement setAttribute:@"xmlns" value:@"http://www.w3.org/2000/svg"];
[newSvgElement setAttribute:@"xmlns:xlink" value:@"http://www.w3.org/1999/xlink"];
[newSvgElement setAttribute:@"cursor" value:@"crosshair"];
[newSvgElement setAttribute:@"height" value:svgHeight];
[newSvgElement setAttribute:@"id" value:@"svg_document"];
[newSvgElement setAttribute:@"width" value:svgWidth];
[newSvgElement setAttribute:@"version" value:@"1.1"];
[newSvgElement setAttribute:@"preserveAspectRatio" value:@"xMidYMid meet"];
[newSvgElement setAttribute:@"viewBox" value:svgViewBox];
[documentElement appendChild:newSvgElement];
svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
}
DOMNode * svgElementNode = [svgElementsList item:0];
topSvgElement = (DOMElement *)svgElementNode;
}
// inject marker ref into DOM
DOMNodeList * defsElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"defs"];
if (defsElementsList.length == 0)
{
DOMElement * newDefsElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"defs"];
DOMElement * firstElement = topSvgElement.firstElementChild;
[topSvgElement insertBefore:newDefsElement refChild:firstElement];
defsElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"defs"];
}
DOMElement * defsElement = (DOMElement *)[defsElementsList item:0];
DOMElement * markerElement = [self getMacsvgTopGroupChildByID:@"_macsvg_highlightPathSegmentMarker" createIfNew:NO];
if (markerElement == NULL)
{
markerElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"marker" ];
[markerElement setAttributeNS:NULL qualifiedName:@"id" value:@"_macsvg_highlightPathSegmentMarker"];
float markerWidthFloat = 4.0f * scaleForDOMElementHandles;
NSString * markerWidthString = [self allocPxString:markerWidthFloat];
float markerHeightFloat = 3.0f * scaleForDOMElementHandles;
NSString * markerHeightString = [self allocPxString:markerHeightFloat];
DOMElement * markerElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"marker" ];
[markerElement setAttributeNS:NULL qualifiedName:@"id" value:@"_macsvg_highlightPathSegmentMarker"];
[markerElement setAttributeNS:NULL qualifiedName:@"viewBox" value:@"0 0 10 10"];
[markerElement setAttributeNS:NULL qualifiedName:@"refX" value:@"10"];
[markerElement setAttributeNS:NULL qualifiedName:@"refY" value:@"5"];
[markerElement setAttributeNS:NULL qualifiedName:@"markerUnits" value:@"strokeWidth"];
//[markerElement setAttributeNS:NULL qualifiedName:@"markerWidth" value:@"4"];
[markerElement setAttributeNS:NULL qualifiedName:@"markerWidth" value:markerWidthString];
//[markerElement setAttributeNS:NULL qualifiedName:@"markerHeight" value:@"3"];
[markerElement setAttributeNS:NULL qualifiedName:@"markerHeight" value:markerHeightString];
[markerElement setAttributeNS:NULL qualifiedName:@"orient" value:@"auto"];
//[markerElement setAttributeNS:NULL qualifiedName:@"stroke" value:selectionHandleColor];
[markerElement setAttributeNS:NULL qualifiedName:@"fill" value:selectionHandleColor];
[markerElement setAttributeNS:NULL qualifiedName:@"style" value:@"overflow : visible;"];
DOMElement * markerPathElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"path" ];
[markerPathElement setAttributeNS:NULL qualifiedName:@"d" value:@"M 0 0 L 10 5 L 0 10 z"];
[markerElement appendChild:markerPathElement];
[defsElement appendChild:markerElement];
}
DOMElement * newHighlightPathSegmentGroup = [domDocument createElementNS:svgNamespace
qualifiedName:@"g"];
[newHighlightPathSegmentGroup setAttributeNS:NULL qualifiedName:@"id" value:@"_macsvg_highlightPathSegmentGroup"];
[newHighlightPathSegmentGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_highlightPathSegmentGroup"];
// inject new newHighlightPathSegmentGroup into DOM
[topSvgElement appendChild:newHighlightPathSegmentGroup];
NSString * elementName = pathDOMElement.nodeName;
if ((self.validElementsForTransformDictionary)[elementName] != NULL)
{
DOMElement * parentElement = (id)pathDOMElement.parentNode;
DOMElement * controlParentElement = NULL;
if (controlParentElement == NULL)
{
// replicate the segment of the DOM path
NSMutableArray * newParentsArray = [[NSMutableArray alloc] init];
BOOL continueCreatingParents = YES;
if (parentElement == NULL)
{
continueCreatingParents = NO;
}
else
{
NSString * firstParentTagName = parentElement.nodeName;
if ([firstParentTagName isEqualToString:@"svg"] == YES)
{
continueCreatingParents = NO;
}
if ([firstParentTagName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
}
while (continueCreatingParents == YES)
{
NSString * parentTagName = parentElement.nodeName;
DOMElement * newControlParentElement = [domDocument createElementNS:svgNamespace
qualifiedName:parentTagName];
NSString * control_Macsvgid = [parentElement getAttribute:@"macsvgid"];
[newControlParentElement setAttributeNS:NULL qualifiedName:@"control_Macsvgid" value:control_Macsvgid];
[newHighlightPathSegmentGroup setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_selectionParent"];
[self copyChildAnimationFromDOMElement:parentElement toDOMElement:newControlParentElement offsetPoint:NSZeroPoint];
DOMSelectionCacheRecord * newDOMSelectionCacheRecord =
[[DOMSelectionCacheRecord alloc] init];
newDOMSelectionCacheRecord.parentElement = parentElement;
newDOMSelectionCacheRecord.controlParentElement = newControlParentElement;
[newParentsArray insertObject:newControlParentElement atIndex:0];
if (parentElement.parentNode == NULL)
{
continueCreatingParents = NO;
}
else
{
DOMNode * nextParentNode = parentElement.parentNode;
NSString * nextParentTagName = nextParentNode.nodeName;
if ([nextParentTagName isEqualToString:@"svg"] == YES)
{
continueCreatingParents = NO;
}
if ([nextParentTagName isEqualToString:@"#document"] == YES)
{
continueCreatingParents = NO;
}
else
{
parentElement = (DOMElement *)nextParentNode;
}
}
}
// inject new elements into DOM from the top down, starting as child of 'newSelectedRectsGroup'
controlParentElement = (DOMElement *)newHighlightPathSegmentGroup;
for (DOMElement * aElement in newParentsArray)
{
[controlParentElement appendChild:aElement];
controlParentElement = (DOMElement *)aElement;
}
}
if (controlParentElement != NULL)
{
// draw the path segment highlight
NSString * pathWidthString = [pathDOMElement getAttribute:@"stroke-width"];
float pathWidth = pathWidthString.integerValue;
if (pathWidth > 0)
{
pathWidth += 2;
selectionStrokeWidth = [NSString stringWithFormat:@"%f", pathWidth];
}
DOMElement * pathSegmentElement = [domDocument createElementNS:svgNamespace
qualifiedName:@"path" ];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"fill" value:@"none"];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"stroke" value:selectionHandleColor];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"pointer-events" value:@"none"]; // disallow selection of section rects
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"class" value:@"_macsvg_highlight_path"];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"stroke-width" value:selectionStrokeWidth];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"marker-end" value:@"url(#_macsvg_highlightPathSegmentMarker)"];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"d" value:pathSegmentString];
NSString * control_Macsvgid = [pathDOMElement getAttribute:@"macsvgid"];
[pathSegmentElement setAttributeNS:NULL qualifiedName:@"control_Macsvgid" value:control_Macsvgid];
[controlParentElement appendChild:pathSegmentElement];
[self copyChildAnimationFromDOMElement:pathDOMElement toDOMElement:pathSegmentElement offsetPoint:NSZeroPoint];
//NSLog(@"selectionRect added %@, %@, %@, %@", bboxXString, bboxYString, bboxWidthString, bboxHeightString);
}
}
// set begin attributes again for animation elements
DOMNodeList * animationElements = [domDocument getElementsByClassName:@"_macsvg_controlAnimation"];
unsigned animationElementsCount = animationElements.length;
for (int i = 0; i < animationElementsCount; i++)
{
DOMElement * controlAnimationElement = (id)[animationElements item:i];
NSString * beginValue = [controlAnimationElement getAttribute:@"begin"];
[controlAnimationElement setAttributeNS:NULL qualifiedName:@"begin" value:beginValue]; // enable animation for element in webkit
}
}
//==================================================================================
// highlightPathSegment:
//==================================================================================
- (IBAction)highlightPathSegment
{
NSUInteger selectedItemsCount = [svgXMLDOMSelectionManager.selectedElementsManager selectedElementsCount];
if (selectedItemsCount == 1)
{
NSXMLElement * selectedXMLElement =
[svgXMLDOMSelectionManager.selectedElementsManager xmlElementAtIndex:0];
DOMElement * selectedDOMElement =
[svgXMLDOMSelectionManager.selectedElementsManager domElementAtIndex:0];
NSString * selectedXMLElementName = selectedXMLElement.name;
if ([selectedXMLElementName isEqualToString:@"path"] == YES)
{
//if (self.pathSegmentIndex >= 0)
if (svgWebKitController.domMouseEventsController.svgPathEditor.pathSegmentIndex >= 0)
{
//NSMutableArray * pathSegmentsArray = svgXMLDOMSelectionManager.pathSegmentsArray;
NSString * pathString = [selectedDOMElement getAttribute:@"d"];
NSMutableArray * pathSegmentsArray = [svgWebKitController.domMouseEventsController.svgPathEditor buildPathSegmentsArrayWithPathString:pathString];
//if (self.pathSegmentIndex < [pathSegmentsArray count])
if (svgWebKitController.domMouseEventsController.svgPathEditor.pathSegmentIndex < pathSegmentsArray.count)
{
NSMutableString * newPathString = [NSMutableString string];
PathFunctions * pathFunctions = macSVGDocumentWindowController.pathFunctions;
NSMutableArray * bezierPathSegmentsArray = [pathFunctions
convertCurvesToAbsoluteCubicBezierWithPathSegmentsArray:pathSegmentsArray];
PathSegment * pathSegment =
bezierPathSegmentsArray[svgWebKitController.domMouseEventsController.svgPathEditor.pathSegmentIndex];
NSString * startXString = pathSegment.xString;
NSString * startYString = pathSegment.yString;
//if (self.pathSegmentIndex > 0)
if (svgWebKitController.domMouseEventsController.svgPathEditor.pathSegmentIndex > 0)
{
// get current starting point from previous segment
PathSegment * previousPathSegment =
pathSegmentsArray[(svgWebKitController.domMouseEventsController.svgPathEditor.pathSegmentIndex - 1)];
float startX = previousPathSegment.absoluteXFloat;
float startY = previousPathSegment.absoluteYFloat;
startXString = [self allocFloatString:startX];
startYString = [self allocFloatString:startY];
}
if (startXString.length == 0)
{
startXString = @"0";
}
if (startYString.length == 0)
{
startYString = @"0";
}
// move to initial position of segment
[newPathString appendString:@"M"];
[newPathString appendString:startXString];
[newPathString appendString:@","];
[newPathString appendString:startYString];
[newPathString appendString:@" "];
unichar commandChar = pathSegment.pathCommand;
NSString * pathCommandString = [NSString stringWithFormat:@"%C", commandChar];
// draw the path segment
switch (commandChar)
{
case 'M': // moveto
case 'm': // moveto
{
//if (self.pathSegmentIndex == 0)
if (svgWebKitController.domMouseEventsController.svgPathEditor.pathSegmentIndex == 0)
{
[newPathString appendString:@"M"];
}
else
{
[newPathString appendString:pathCommandString];
}
NSString * xString = pathSegment.absoluteXString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.absoluteYString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'L': // lineto
{
[newPathString appendString:@"L"];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'l': // lineto
{
[newPathString appendString:@"l"];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'H': // horizontal lineto
{
[newPathString appendString:@"H"];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@" "];
break;
}
case 'h': // horizontal lineto
{
[newPathString appendString:@"h"];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@" "];
break;
}
case 'V': // vertical lineto
{
[newPathString appendString:@"V"];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'v': // vertical lineto
{
[newPathString appendString:@"v"];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'C': // curveto
{
[newPathString appendString:@"C"];
NSString * x1String = pathSegment.x1String;
[newPathString appendString:x1String];
[newPathString appendString:@","];
NSString * y1String = pathSegment.y1String;
[newPathString appendString:y1String];
[newPathString appendString:@" "];
NSString * x2String = pathSegment.x2String;
[newPathString appendString:x2String];
[newPathString appendString:@","];
NSString * y2String = pathSegment.y2String;
[newPathString appendString:y2String];
[newPathString appendString:@" "];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'c': // curveto
{
[newPathString appendString:@"c"];
NSString * x1String = pathSegment.x1String;
[newPathString appendString:x1String];
[newPathString appendString:@","];
NSString * y1String = pathSegment.y1String;
[newPathString appendString:y1String];
[newPathString appendString:@" "];
NSString * x2String = pathSegment.x2String;
[newPathString appendString:x2String];
[newPathString appendString:@","];
NSString * y2String = pathSegment.y2String;
[newPathString appendString:y2String];
[newPathString appendString:@" "];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'S': // smooth curveto
{
[newPathString appendString:@"S"];
NSString * x2String = pathSegment.x2String;
[newPathString appendString:x2String];
[newPathString appendString:@","];
NSString * y2String = pathSegment.y2String;
[newPathString appendString:y2String];
[newPathString appendString:@" "];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 's': // smooth curveto
{
[newPathString appendString:@"s"];
NSString * x2String = pathSegment.x2String;
[newPathString appendString:x2String];
[newPathString appendString:@","];
NSString * y2String = pathSegment.y2String;
[newPathString appendString:y2String];
[newPathString appendString:@" "];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'Q': // quadratic Bezier curve
{
[newPathString appendString:@"Q"];
NSString * x1String = pathSegment.x1String;
[newPathString appendString:x1String];
[newPathString appendString:@","];
NSString * y1String = pathSegment.y1String;
[newPathString appendString:y1String];
[newPathString appendString:@" "];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'q': // quadratic Bezier curve
{
[newPathString appendString:@"q"];
NSString * x1String = pathSegment.x1String;
[newPathString appendString:x1String];
[newPathString appendString:@","];
NSString * y1String = pathSegment.y1String;
[newPathString appendString:y1String];
[newPathString appendString:@" "];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'T': // smooth quadratic Bezier curve
{
[newPathString appendString:@"T"];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 't': // smooth quadratic Bezier curve
{
[newPathString appendString:@"t"];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'A': // elliptical arc
{
[newPathString appendString:@"A"];
NSString * rxString = pathSegment.rxString;
[newPathString appendString:rxString];
[newPathString appendString:@","];
NSString * ryString = pathSegment.ryString;
[newPathString appendString:ryString];
[newPathString appendString:@" "];
NSString * dataXAxisRotationString = pathSegment.xAxisRotationString;
[newPathString appendString:dataXAxisRotationString];
[newPathString appendString:@" "];
NSString * dataLargeArcString = pathSegment.largeArcFlagString;
[newPathString appendString:dataLargeArcString];
[newPathString appendString:@" "];
NSString * sweepString = pathSegment.sweepFlagString;
[newPathString appendString:sweepString];
[newPathString appendString:@" "];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'a': // elliptical arc
{
[newPathString appendString:@"a"];
NSString * rxString = pathSegment.rxString;
[newPathString appendString:rxString];
[newPathString appendString:@","];
NSString * ryString = pathSegment.ryString;
[newPathString appendString:ryString];
[newPathString appendString:@" "];
NSString * aXAxisRotationString = pathSegment.xAxisRotationString;
[newPathString appendString:aXAxisRotationString];
[newPathString appendString:@" "];
NSString * largeArcString = pathSegment.largeArcFlagString;
[newPathString appendString:largeArcString];
[newPathString appendString:@" "];
NSString * sweepString = pathSegment.sweepFlagString;
[newPathString appendString:sweepString];
[newPathString appendString:@" "];
NSString * xString = pathSegment.xString;
[newPathString appendString:xString];
[newPathString appendString:@","];
NSString * yString = pathSegment.yString;
[newPathString appendString:yString];
[newPathString appendString:@" "];
break;
}
case 'Z': // closepath
{
[newPathString appendString:@" Z "];
break;
}
case 'z': // closepath
{
[newPathString appendString:@" z "];
break;
}
}
[self highlightPathSegmentInDOM:newPathString forDOMElement:selectedDOMElement];
}
else
{
//self.pathSegmentIndex = -1; // index was invalid
svgWebKitController.domMouseEventsController.svgPolylineEditor.polylinePointIndex = -1; // index was invalid
}
}
}
}
}
//==================================================================================
// keyDOMElement
//==================================================================================
- (DOMElement *)keyDOMElement
{
DOMElement * keyDOMElement = NULL;
// try fast method first
if (self.domElementForHandles != NULL)
{
if (self.domElementForHandlesCreationTime != 0)
{
time_t lastWebViewLoadTime = svgWebKitController.lastLoadFinishedTime;
if (lastWebViewLoadTime != 0)
{
if (lastWebViewLoadTime < self.domElementForHandlesCreationTime)
{
keyDOMElement = self.domElementForHandles;
}
}
}
}
if (keyDOMElement == NULL)
{
/*
NSString * selectionHandlesGroupID = @"_macsvg_selectionHandlesGroup";
DOMDocument * domDocument = [[svgWebView mainFrame] DOMDocument];
DOMElement * domSelectedRectsGroup = [domDocument getElementById:selectionHandlesGroupID];
*/
DOMElement * domSelectedRectsGroup = [self getMacsvgTopGroupChildByID:@"_macsvg_selectionHandlesGroup" createIfNew:NO];
if (domSelectedRectsGroup != NULL)
{
NSString * key_Macsvgid = [domSelectedRectsGroup getAttribute:@"key_Macsvgid"];
keyDOMElement = [svgWebKitController domElementForMacsvgid:key_Macsvgid];
}
}
return keyDOMElement;
}
//==================================================================================
// keyXMLElement
//==================================================================================
- (NSXMLElement *)keyXMLElement
{
NSXMLElement * keyXMLElement = NULL;
/*
NSString * selectionHandlesGroupID = @"_macsvg_selectionHandlesGroup";
DOMDocument * domDocument = [[svgWebView mainFrame] DOMDocument];
DOMElement * domSelectedRectsGroup = [domDocument getElementById:selectionHandlesGroupID];
*/
DOMElement * domSelectedRectsGroup = [self getMacsvgTopGroupChildByID:@"_macsvg_selectionHandlesGroup" createIfNew:NO];
if (domSelectedRectsGroup != NULL)
{
NSString * key_Macsvgid = [domSelectedRectsGroup getAttribute:@"key_Macsvgid"];
MacSVGDocument * macSVGDocument = macSVGDocumentWindowController.document;
keyXMLElement = [macSVGDocument xmlElementForMacsvgid:key_Macsvgid];
}
//DOMElement * keyDOMElement = [self keyDOMElement]; // TEST remove after testing
return keyXMLElement;
}
//==================================================================================
// updateDOMSelectionRectsAndHandles
//==================================================================================
- (void) updateDOMSelectionRectsAndHandles
{
DOMElement * keyDOMElement = [self keyDOMElement];
DOMElement * selectedRectsGroup = [self getMacsvgTopGroupChildByID:@"_macsvg_selectedRectsGroup" createIfNew:NO];
if (selectedRectsGroup != NULL)
{
[self makeDOMSelectionRects];
[self makeDOMSelectionHandles:keyDOMElement];
}
else if (keyDOMElement != NULL)
{
[self makeDOMSelectionHandles:keyDOMElement];
}
NSInteger animationEnabled = macSVGDocumentWindowController.enableAnimationCheckbox.state;
if (animationEnabled != 0)
{
DOMDocument * domDocument = svgWebView.mainFrame.DOMDocument;
DOMNodeList * svgElementsList = [domDocument getElementsByTagNameNS:svgNamespace localName:@"svg"];
if (svgElementsList.length > 0)
{
NSString * currentTimeString = (macSVGDocumentWindowController.svgWebKitController.currentTimeTextField).stringValue;
float currentTimeValue = [currentTimeString floatValue];
[macSVGDocumentWindowController.animationTimelineView setPlayHeadPosition:currentTimeValue];
NSNumber * newTimeValueNumber = [NSNumber numberWithFloat:currentTimeValue];
DOMNode * svgElementNode = [svgElementsList item:0];
DOMElement * svgElement = (DOMElement *)svgElementNode;
NSArray * setCurrentTimeArgumentsArray = @[newTimeValueNumber];
[svgElement callWebScriptMethod:@"setCurrentTime" withArguments:setCurrentTimeArgumentsArray]; // call JavaScript function
[svgElement callWebScriptMethod:@"forceRedraw" withArguments:NULL]; // call JavaScript function
[macSVGDocumentWindowController.animationTimelineView setPlayHeadPosition:currentTimeValue];
}
}
}
//==================================================================================
// updateSelectionRectsDOMElement:
//==================================================================================
- (void) updateSelectionRectsDOMElement:(DOMElement *)selectionRectsDOMElement
{
// top-level caller can send selectionRectsDOMElement with <g id='selectedRectsGroup'>
// then, this method will recursively handle all child elements
//NSLog(@"enter updateSelectionRectsDOMElement");
// recursive method
NSString * nodeName = selectionRectsDOMElement.nodeName;
NSString * control_Macsvgid = [selectionRectsDOMElement getAttribute:@"control_Macsvgid"];
if (control_Macsvgid == NULL)
{
NSLog(@"control_Macsvgid = NULL");
}
else
{
if (control_Macsvgid.length == 0)
{
NSLog(@"control_Macsvgid is empty");
}
}
if ([nodeName isEqualToString:@"rect"] == YES)
{
DOMElement * rectElement = (id)selectionRectsDOMElement;
if (control_Macsvgid != NULL)
{
if ([control_Macsvgid isEqualToString:@""] == NO)
{
DOMElement * originalElement = [svgWebKitController domElementForMacsvgid:control_Macsvgid];
MacSVGAppDelegate * macSVGAppDelegate = (MacSVGAppDelegate *)NSApp.delegate;
WebKitInterface * webKitInterface = [macSVGAppDelegate webKitInterface];
NSRect boundingBox = [webKitInterface bBoxForDOMElement:originalElement];
//NSRect boundingBox = [webKitInterface bBoxForDOMElement:originalElement globalContext:[[svgWebView mainFrame] globalContext]];
if (NSIsEmptyRect(boundingBox) == NO)
{
float bboxX = boundingBox.origin.x - 2;
float bboxY = boundingBox.origin.y - 2;
float bboxWidth = boundingBox.size.width + 4;
float bboxHeight = boundingBox.size.height + 4;
NSRect expandedRect = NSMakeRect(bboxX, bboxY, bboxWidth, bboxHeight);
[webKitInterface setRect:expandedRect forElement:rectElement];
NSString * transformAttribute = [originalElement getAttribute:@"transform"];
if (transformAttribute != NULL)
{
if (transformAttribute.length > 0)
{
[rectElement setAttributeNS:NULL qualifiedName:@"transform" value:transformAttribute];
}
else
{
[rectElement setAttributeNS:NULL qualifiedName:@"transform" value:@""];
}
}
else
{
[rectElement removeAttributeNS:NULL localName:@"transform"];
}
}
}
}
}
if ([nodeName isEqualToString:@"g"] == YES)
{
DOMElement * gElement = (id)selectionRectsDOMElement;
if (control_Macsvgid != NULL)
{
if ([control_Macsvgid isEqualToString:@""] == NO)
{
DOMElement * originalElement = [svgWebKitController domElementForMacsvgid:control_Macsvgid];
NSString * transformAttribute = [originalElement getAttribute:@"transform"];
if (transformAttribute != NULL)
{
if (transformAttribute.length > 0)
{
[gElement setAttributeNS:NULL qualifiedName:@"transform" value:transformAttribute];
}
else
{
[gElement setAttributeNS:NULL qualifiedName:@"transform" value:@""];
}
}
else
{
[gElement removeAttributeNS:NULL localName:@"transform"];
}
}
}
}
int selectedRectsCount = selectionRectsDOMElement.childElementCount;
for (int j = 0; j < selectedRectsCount; j++)
{
// recursive call for child elements
DOMElement * childElement = (id)[(id)selectionRectsDOMElement.childNodes item:j];
[self updateSelectionRectsDOMElement:childElement];
}
}
//==================================================================================
// floatFromString:
//==================================================================================
-(float) floatFromString:(NSString *)valueString
{
float floatValue = 0;
NSMutableString * trimmedString = [[NSMutableString alloc] init];
NSUInteger inputLength = valueString.length;
for (int i = 0; i < inputLength; i++)
{
unichar aChar = [valueString characterAtIndex:i];
BOOL validChar = YES;
if (aChar < '0') validChar = NO;
if (aChar > '9') validChar = NO;
if (aChar == '.') validChar = YES;
if (aChar == '-') validChar = YES;
if (validChar == NO)
{
break;
}
NSString * charString = [[NSString alloc] initWithFormat:@"%C", aChar];
[trimmedString appendString:charString];
}
floatValue = trimmedString.floatValue;
return floatValue;
}
//==================================================================================
// allocFloatString:
//==================================================================================
- (NSMutableString *)allocFloatString:(float)aFloat
{
NSMutableString * aString = [[NSMutableString alloc] initWithFormat:@"%f", aFloat];
BOOL continueTrim = YES;
while (continueTrim == YES)
{
NSUInteger stringLength = aString.length;
if (stringLength <= 1)
{
continueTrim = NO;
}
else
{
unichar lastChar = [aString characterAtIndex:(stringLength - 1)];
if (lastChar == '0')
{
NSRange deleteRange = NSMakeRange(stringLength - 1, 1);
[aString deleteCharactersInRange:deleteRange];
}
else if (lastChar == '.')
{
NSRange deleteRange = NSMakeRange(stringLength - 1, 1);
[aString deleteCharactersInRange:deleteRange];
continueTrim = NO;
}
else
{
continueTrim = NO;
}
}
}
return aString;
}
//==================================================================================
// allocPxString:
//==================================================================================
- (NSMutableString *)allocPxString:(float)aFloat
{
NSMutableString * aString = [[NSMutableString alloc] initWithFormat:@"%f", aFloat];
BOOL continueTrim = YES;
while (continueTrim == YES)
{
NSUInteger stringLength = aString.length;
if (stringLength <= 1)
{
continueTrim = NO;
}
else
{
unichar lastChar = [aString characterAtIndex:(stringLength - 1)];
if (lastChar == '0')
{
NSRange deleteRange = NSMakeRange(stringLength - 1, 1);
[aString deleteCharactersInRange:deleteRange];
}
else if (lastChar == '.')
{
NSRange deleteRange = NSMakeRange(stringLength - 1, 1);
[aString deleteCharactersInRange:deleteRange];
continueTrim = NO;
}
else
{
continueTrim = NO;
}
}
}
[aString appendString:@"px"];
return aString;
}
@end
#pragma clang diagnostic pop