Last active
March 22, 2016 04:53
-
-
Save Raztor0/fee5778a35e52f9b922a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import xml.etree.ElementTree as ET | |
import xml.dom.minidom as minidom | |
import sys | |
import uuid | |
def main(argv): | |
xibPath = '' | |
tree = '' | |
attemptFixup = False | |
try: | |
xibPath = argv[0] | |
if(len(argv) == 2): | |
attemptFixup = argv[1] == '--attempt-fixup' | |
tree = ET.parse(xibPath) | |
except Exception, e: | |
print e | |
sys.exit(2) | |
# Returns a string of the format xxx-xx-xxx | |
def getUUID(): | |
myid = str(uuid.uuid4()).strip('-') | |
myid = myid[:8] | |
myid = myid[:3] + '-' + myid[3:5] + '-' + myid[5:8] | |
return myid | |
''' | |
copy and paste from http://effbot.org/zone/element-lib.htm#prettyprint | |
it walks your tree and adds spaces and newlines so the tree is | |
printed in a nice way | |
''' | |
def indent(elem, level=0): | |
i = "\n" + level*" " | |
if len(elem): | |
if not elem.text or not elem.text.strip(): | |
elem.text = i + " " | |
if not elem.tail or not elem.tail.strip(): | |
elem.tail = i | |
for elem in elem: | |
indent(elem, level+1) | |
if not elem.tail or not elem.tail.strip(): | |
elem.tail = i | |
else: | |
if level and (not elem.tail or not elem.tail.strip()): | |
elem.tail = i | |
# Grab some relevant elements | |
document = tree.getroot() | |
objects = document.find("objects") | |
superview = objects.find("view") | |
superviewframe = superview.find('rect') | |
superviewId = superview.attrib['id'] | |
subviews = superview.find("subviews") | |
constraints = superview.find("constraints") | |
if superview == None or subviews == None: | |
print 'Cannot scrollify a xib with no views' | |
sys.exit(2) | |
# Keep track of the constraints currently linked to the superview | |
constraintsToConvert = constraints.findall(".//constraint[@secondItem='" + superviewId+ "']") | |
for constraint in constraints: | |
# Some constraints which point to the superview don't specify a 'firstItem' attribute | |
if constraint.get('firstItem') == None and constraint.get('secondItem') in (o.get('id') for o in subviews): | |
constraintsToConvert.append(constraint) | |
for constraint in constraintsToConvert: | |
constraints.remove(constraint) | |
# Keep track of the bottom-most subview for later | |
currentBottom = 0 | |
bottomMostView = subviews[0] | |
for view in subviews.findall(".//rect[@key='frame']/.."): | |
rect = view.find("rect") | |
bottom = float(rect.attrib['y']) + float(rect.attrib['height']) | |
if bottom >= currentBottom: | |
currentBottom = bottom | |
bottomMostView = view | |
# Create the scrollview | |
scrollviewId = getUUID() | |
scrollview = ET.Element('scrollView', {'clipsSubviews': 'YES', 'contentMode': 'scaleToFill', 'id' : scrollviewId, 'multipleTouchEnabled': 'YES', 'translatesAutoresizingMaskIntoConstraints': 'NO'}) | |
scrollview.insert(0, superviewframe) | |
# Add a constraints section on the scrollview | |
scrollviewConstraints = ET.Element('constraints') | |
scrollview.append(scrollviewConstraints) | |
# Add a subviews section on the scrollview | |
scrollviewSubviews = ET.Element('subviews') | |
scrollview.append(scrollviewSubviews) | |
# Add scrollview constraints to superview | |
for constraintAttribute in ['leading', 'trailing', 'top', 'bottom']: | |
scrollviewConstraint = ET.Element('constraint', {'firstItem': scrollviewId, 'firstAttribute': constraintAttribute, 'secondItem': superviewId, 'secondAttribute': constraintAttribute, 'id': getUUID()}) | |
constraints.insert(0, scrollviewConstraint) | |
# Create the container view | |
containerViewId = getUUID() | |
containerview = ET.Element('view', {'contentMode': 'scaleToFill', 'translatesAutoresizingMaskIntoConstraints': 'NO', 'id': containerViewId}) | |
# Add it to the scrollview's subviews | |
scrollviewSubviews.insert(1, containerview) | |
# Give it a background colour | |
bgColour = ET.Element('color', {'key': 'backgroundColor', 'white': '1', 'alpha': '1', 'colorSpace': 'calibratedWhite'}) | |
containerview.insert(0, bgColour) | |
# And a frame | |
containerFrame = ET.Element('rect', {'key': 'frame', 'x': '0', 'y': '0', 'width': superviewframe.attrib['width'], 'height': str(currentBottom)}) | |
containerview.insert(1, containerFrame) | |
# And its own subviews section | |
containerSubviews = ET.Element('subviews') | |
containerview.insert(2, containerSubviews) | |
# And its own constraints section | |
containerConstraints = ET.Element('constraints') | |
containerview.insert(3, containerConstraints) | |
# Move the original subviews to the container | |
for view in subviews: | |
containerSubviews.append(view) | |
# Clear the old subviews | |
subviews.clear() | |
# Update the original subview constraints to point to our container | |
for constraint in constraintsToConvert: | |
if constraint.get('firstItem') != None: | |
constraint.set('secondItem', containerViewId) | |
containerConstraints.append(constraint) | |
# Add width constraint for our container | |
widthConstraint = ET.Element('constraint', {'firstItem': containerViewId, 'firstAttribute': 'width', 'secondItem': superviewId, 'secondAttribute': 'width', 'id': getUUID()}) | |
constraints.append(widthConstraint) | |
# Set the container constraints on the scrollview | |
for constraintAttribute in ['leading', 'trailing', 'top', 'bottom']: | |
containerConstraint = ET.Element('constraint', {'firstItem': containerViewId, 'firstAttribute': constraintAttribute, 'secondItem': scrollviewId, 'secondAttribute': constraintAttribute, 'id': getUUID()}) | |
scrollviewConstraints.insert(0, containerConstraint) | |
if attemptFixup: | |
# Constrain the bottom of the container to the bottom-most item in our hierarchy | |
bottomConstraint = ET.Element('constraint', {'firstItem': containerViewId, 'firstAttribute': 'bottom', 'secondItem': bottomMostView.get('id'), 'secondAttribute': 'bottom', 'id': getUUID()}) | |
containerConstraints.append(bottomConstraint) | |
# Finally add the scrollview to the hierarchy | |
subviews.insert(0, scrollview) | |
indent(document) | |
tree.write(xibPath, xml_declaration=True, encoding='utf-8', method="xml") | |
if __name__ == "__main__": | |
main(sys.argv[1:]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment