diff --git a/tools/vsimporter/xib2nib/src/NIBWriter.cpp b/tools/vsimporter/xib2nib/src/NIBWriter.cpp index 2054261883..214ae939d5 100644 --- a/tools/vsimporter/xib2nib/src/NIBWriter.cpp +++ b/tools/vsimporter/xib2nib/src/NIBWriter.cpp @@ -21,8 +21,7 @@ #include "UIProxyObject.h" #include #include -#include "UIViewController.h" -#include "..\WBITelemetry\WBITelemetry.h" +#include "../WBITelemetry/WBITelemetry.h" int curPlaceholder = 1; @@ -79,7 +78,8 @@ XIBObject* NIBWriter::AddOutputObject(XIBObject* pObj) { } typedef struct { - int _a, _b; + int _numHeaders; + int _sizeDw; int _numObjects; // 2 int _objectsOffset; // 3 int _numKeyNames; // 4 @@ -129,6 +129,8 @@ NIBWriter::NIBWriter(FILE* out) { _baseObject = NULL; _connections = NULL; _visibleWindows = NULL; + _minimumDeploymentTarget = DEPLOYMENT_TARGET_RECENT; + _wasLimitedByDeplymentTarget = false; fpOut = out; } @@ -138,6 +140,8 @@ NIBWriter::NIBWriter(FILE* out, XIBDictionary* externalReferences, XIBObject* ba _baseObject = NULL; _connections = NULL; _visibleWindows = NULL; + _minimumDeploymentTarget = DEPLOYMENT_TARGET_RECENT; + _wasLimitedByDeplymentTarget = false; fpOut = out; curPlaceholder = 1; @@ -147,6 +151,7 @@ NIBWriter::NIBWriter(FILE* out, XIBDictionary* externalReferences, XIBObject* ba _connections = new XIBArray(); _topObjects = new XIBArray(); _visibleWindows = new XIBArray(); + _keyValuePairs = new XIBArray(); _accessibilityObjects = new XIBAccessibilityArray(); } @@ -165,7 +170,7 @@ void NIBWriter::WriteObjects() { nibRoot->AddMember("UINibConnectionsKey", _connections); nibRoot->AddMember("UINibVisibleWindowsKey", _visibleWindows); nibRoot->AddMember("UINibAccessibilityConfigurationsKey", _accessibilityObjects); - nibRoot->AddMember("UINibKeyValuePairsKey", new XIBArray()); + nibRoot->AddMember("UINibKeyValuePairsKey", _keyValuePairs); AddOutputObject(nibRoot); // Sort connection records alphabetically using stable, uh, bubble sort @@ -233,6 +238,10 @@ void NIBWriter::AddOutletConnection(XIBObject* src, XIBObject* dst, char* propNa } XIBObject* NIBWriter::AddProxy(char* propName) { + XIBObject* existingProxy = NIBWriter::FindProxy(propName); + if (existingProxy) + return existingProxy; + UIProxyObject* newProxy = new UIProxyObject(); newProxy->_identifier = strdup(propName); _allUIObjects->AddMember(NULL, newProxy); @@ -290,67 +299,6 @@ XIBObject* NIBWriter::GetProxyFor(XIBObject* obj) { return newProxy; } -std::map _g_exportedControllers; - -void NIBWriter::ExportAllControllers() { - for (const char* cur : UIViewController::_viewControllerNames) { - ExportController(cur); - } -} - -void NIBWriter::ExportController(const char* controllerId) { - char szFilename[255]; - - XIBObject* controller = XIBObject::findReference(controllerId); - UIViewController* uiViewController = dynamic_cast(controller); - if (!uiViewController) { - // object isn't really a controller - printf("Object %s is not a controller\n", controller->stringValue()); - return; - } - - const char* controllerIdentifier = uiViewController->_storyboardIdentifier; - if (controllerIdentifier == NULL) { - // not all viewcontrollers will have a storyboard identifier. If they don't use the controller Id for the key. - controllerIdentifier = controllerId; - } - - // Check if we've already written out the controller - if (_g_exportedControllers.find(controllerId) != _g_exportedControllers.end()) { - return; - } - - sprintf(szFilename, "%s.nib", controllerIdentifier); - - _g_exportedControllers[controllerIdentifier] = controllerIdentifier; - - XIBArray* objects = (XIBArray*)controller->_parent; - - printf("Writing %s\n", GetOutputFilename(szFilename).c_str()); - FILE* fpOut = fopen(GetOutputFilename(szFilename).c_str(), "wb"); - - NIBWriter* writer = new NIBWriter(fpOut, NULL, NULL); - - XIBObject* firstResponderProxy = writer->AddProxy("IBFirstResponder"); - XIBObject* ownerProxy = writer->AddProxy("IBFilesOwner"); - XIBObject* storyboard = writer->AddProxy("UIStoryboardPlaceholder"); - - XIBArray* arr = (XIBArray*)objects; - for (int i = 0; i < arr->count(); i++) { - XIBObject* curObj = arr->objectAtIndex(i); - - writer->ExportObject(curObj); - if (curObj->getAttrib("sceneMemberID")) { - if (strcmp(curObj->getAttrib("sceneMemberID"), "viewController") == 0) { - writer->AddOutletConnection(ownerProxy, curObj, "sceneViewController"); - } - } - } - - writer->WriteObjects(); - - fclose(fpOut); -} void NIBWriter::WriteData() { fwrite("NIBArchive", 10, 1, fpOut); @@ -379,11 +327,9 @@ void NIBWriter::WriteData() { for (int i = 0; i < classNames._numStrings; i++) { char* pName = classNames._stringTable[i]; int len = strlen(pName) + 1; - WriteInt(len, 2); - if (len == 0x1b) { - int filler = 6; - fwrite(&filler, 1, 4, fpOut); - } + WriteInt(len, 1); + int tp = 0x80; + fwrite(&tp, 1, 1, fpOut); fwrite(pName, 1, len, fpOut); header._numClassNames++; @@ -402,7 +348,7 @@ void NIBWriter::WriteData() { for (int i = 0; i < keyNames._numStrings; i++) { char* pName = keyNames._stringTable[i]; - int len = strlen(pName) + 1; + int len = strlen(pName); WriteInt(len, 1); fwrite(pName, 1, len, fpOut); @@ -451,6 +397,9 @@ void NIBWriter::WriteData() { header._numObjects++; } + header._numHeaders = 1; + header._sizeDw = 9; + fseek(fpOut, headerPos, SEEK_SET); fwrite(&header, sizeof(header), 1, fpOut); } diff --git a/tools/vsimporter/xib2nib/src/NIBWriter.h b/tools/vsimporter/xib2nib/src/NIBWriter.h index f8cde440a6..3c1c38ff81 100644 --- a/tools/vsimporter/xib2nib/src/NIBWriter.h +++ b/tools/vsimporter/xib2nib/src/NIBWriter.h @@ -32,6 +32,10 @@ #define NIBOBJ_NULL 0x09 #define NIBOBJ_UID 0x0A +#define DEPLOYMENT_TARGET_IOS9 0x090000 +#define DEPLOYMENT_TARGET_IOS11 0x0B0000 +#define DEPLOYMENT_TARGET_RECENT DEPLOYMENT_TARGET_IOS11 + class ProxiedObject { public: XIBObject *_obj, *_proxyObj; @@ -48,20 +52,21 @@ class NIBWriter { FILE* fpOut; public: + uint32_t _minimumDeploymentTarget; + bool _wasLimitedByDeplymentTarget; XIBObject* _allUIObjects; XIBObject* _connections; XIBObject* _baseObject; XIBObject* _topObjects; XIBObject* _accessibilityObjects; XIBObject* _visibleWindows; + XIBObject* _keyValuePairs; XIBDictionary* _externalReferencesDictionary; NIBWriter(FILE* out); NIBWriter(FILE* out, XIBDictionary* externalRefsDict, XIBObject* base); - static void ExportController(const char* controllerId); - static void ExportAllControllers(); void ExportObject(XIBObject* obj); void WriteObjects(); XIBObject* AddOutputObject(XIBObject* pObj); @@ -76,4 +81,4 @@ class NIBWriter { XIBObject* GetProxyFor(XIBObject* obj); }; -#endif \ No newline at end of file +#endif diff --git a/tools/vsimporter/xib2nib/src/NSLayoutConstraint.cpp b/tools/vsimporter/xib2nib/src/NSLayoutConstraint.cpp index 6a1583834f..6551a511ee 100644 --- a/tools/vsimporter/xib2nib/src/NSLayoutConstraint.cpp +++ b/tools/vsimporter/xib2nib/src/NSLayoutConstraint.cpp @@ -16,8 +16,10 @@ #include "NSLayoutConstraint.h" #include "UIView.h" +#include "UILayoutGuide.h" #include +#include #include std::map storyToLayout = { { "left", NSLayoutAttributeLeft }, @@ -41,17 +43,24 @@ std::map storyToLayout = { { "left", NSLayoutAtt { "centerXWithinMargins", NSLayoutAttributeCenterXWithinMargins }, { "centerYWithinMargins", NSLayoutAttributeCenterYWithinMargins } }; +static std::map storyToRelation = { + { "greaterThanOrEqual", NSLayoutRelationGreaterThanOrEqual }, + { "lessThanOrEqual", NSLayoutRelationLessThanOrEqual }}; + NSLayoutConstraint::NSLayoutConstraint() { _firstItem = NULL; _secondItem = NULL; _firstAttribute = NSLayoutAttributeNotAnAttribute; _secondAttribute = NSLayoutAttributeNotAnAttribute; _relation = NSLayoutRelationEqual; - _multiplier = 1.0f; + _multiplier = 1.0; _priority = NSLayoutPriorityRequired; - _constant = 0.0f; - _symbolicConstant = 0.0f; + _constant = 0.0; + _symbolicConstant = 0.0; _hasSymbolicConstant = false; + _layoutIdentifier = NULL; + _placeholder = false; + _exportDefaultValues = false; } void NSLayoutConstraint::InitFromXIB(XIBObject* obj) { @@ -69,10 +78,10 @@ void NSLayoutConstraint::InitFromXIB(XIBObject* obj) { _multiplier = obj->FindMember("multiplier")->floatValue(); } if (obj->FindMember("priority")) { - _priority = obj->FindMember("priority")->floatValue(); + _priority = obj->FindMember("priority")->intValue(); } if (obj->FindMember("constant") && obj->FindMember("constant")->FindMember("value")) { - if (obj->FindMember("constant")->ClassName() == "IBLayoutConstant") { + if (strcmp(obj->FindMember("constant")->ClassName(), "IBLayoutConstant") == 0) { _constant = obj->FindMember("constant")->FindMember("value")->floatValue(); } else { _hasSymbolicConstant = true; @@ -92,18 +101,18 @@ void NSLayoutConstraint::InitFromStory(XIBObject* obj) { ObjectConverterSwapper::InitFromStory(obj); const char* attr; - if (attr = obj->getAttrAndHandle("firstAttribute")) { + if ((attr = obj->getAttrAndHandle("firstAttribute"))) { if (storyToLayout.find(attr) != storyToLayout.end()) { _firstAttribute = storyToLayout[attr]; } } - if (attr = obj->getAttrAndHandle("secondAttribute")) { + if ((attr = obj->getAttrAndHandle("secondAttribute"))) { if (storyToLayout.find(attr) != storyToLayout.end()) { _secondAttribute = storyToLayout[attr]; } } - if (attr = obj->getAttrAndHandle("constant")) { + if ((attr = obj->getAttrAndHandle("constant"))) { if (obj->getAttrAndHandle("symbolic") && strcmp(obj->getAttrAndHandle("symbolic"), "YES") == 0) { _hasSymbolicConstant = true; _symbolicConstant = strtod(attr, NULL); @@ -111,58 +120,90 @@ void NSLayoutConstraint::InitFromStory(XIBObject* obj) { _constant = strtod(attr, NULL); } } - if (attr = obj->getAttrAndHandle("priority")) { - _priority = strtod(attr, NULL); + if ((attr = obj->getAttrAndHandle("priority"))) { + _priority = std::stoi(attr, NULL); } - if (attr = obj->getAttrAndHandle("multiplier")) { - _priority = strtod(attr, NULL); + if ((attr = obj->getAttrAndHandle("multiplier"))) { + char *separator; + _multiplier = strtod(attr, &separator); + if (*separator == ':') { + // it is multiplier in form of "100:200" + double div = strtod(separator + 1, NULL); + _multiplier /= div; + } } - if (attr = getAttrAndHandle("secondItem")) { + if ((attr = getAttrAndHandle("secondItem"))) { _secondItem = findReference(attr); assert(_secondItem); } - if (attr = getAttrAndHandle("firstItem")) { + + if ((attr = getAttrAndHandle("firstItem"))) { _firstItem = findReference(attr); assert(_firstItem); } + if ((attr = obj->getAttrAndHandle("relation"))) { + if (storyToRelation.find(attr) != storyToRelation.end()) { + _relation = storyToRelation[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("placeholder"))) { + _placeholder = strcmp(attr, "YES") == 0; + } + _outputClassName = "NSLayoutConstraint"; } void NSLayoutConstraint::Awaken() { if (!_firstItem) { // Alludes to superview. - if (_secondItem && _secondItem->_parent) { - _firstItem = dynamic_cast(_secondItem->_parent->_parent); - assert(_firstItem); - } else { - _firstItem = dynamic_cast(_parent->_parent); - assert(_firstItem); - } + _firstItem = dynamic_cast(_parent->_parent); + assert(_firstItem); } } void NSLayoutConstraint::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { AddInt(writer, "NSFirstAttribute", _firstAttribute); - AddInt(writer, "NSSecondAttribute", _secondAttribute); + if (_secondAttribute) + AddInt(writer, "NSSecondAttribute", _secondAttribute); - AddInt(writer, "NSRelation", _relation); + if (_exportDefaultValues || _relation != NSLayoutRelationEqual) + AddInt(writer, "NSRelation", _relation); if (_firstItem) - AddOutputMember(writer, "NSFirstItem", _firstItem); + AddOutputMember(writer, "NSFirstItem", substituteItemUnsupported(writer, _firstItem)); if (_secondItem) - AddOutputMember(writer, "NSSecondItem", _secondItem); + AddOutputMember(writer, "NSSecondItem", substituteItemUnsupported(writer, _secondItem)); - AddOutputMember(writer, "NSMultiplier", new XIBObjectFloat(_multiplier)); - AddInt(writer, "NSPriority", _priority); + if (_exportDefaultValues || _multiplier != 1.0f) + AddOutputMember(writer, "NSMultiplier", new XIBObjectDouble(_multiplier)); + if (_exportDefaultValues || _priority != NSLayoutPriorityRequired) + AddInt(writer, "NSPriority", _priority); if (_hasSymbolicConstant) { - AddOutputMember(writer, "NSSymbolicConstant", new XIBObjectFloat(_symbolicConstant)); + AddOutputMember(writer, "NSSymbolicConstant", new XIBObjectDouble(_symbolicConstant)); } else { - AddOutputMember(writer, "NSConstant", new XIBObjectFloat(_constant)); + if (_exportDefaultValues || _constant != 0) + AddOutputMember(writer, "NSConstant", new XIBObjectDouble(_constant)); } + if (_layoutIdentifier) + AddString(writer, "NSLayoutIdentifier", _layoutIdentifier); + ObjectConverterSwapper::ConvertStaticMappings(writer, obj); -} \ No newline at end of file +} + +XIBObject* NSLayoutConstraint::substituteItemUnsupported(NIBWriter* writer, XIBObject* item){ + if (writer->_minimumDeploymentTarget < DEPLOYMENT_TARGET_IOS11 && (strcmp(item->_outputClassName, "UILayoutGuide") == 0)) { + writer->_wasLimitedByDeplymentTarget = true; + // constraint to layout guide that is not supported, replace them to view + UILayoutGuide *guide = (UILayoutGuide*)item; + if (guide->_owningView) + return guide->_owningView; + } + + return item; +} diff --git a/tools/vsimporter/xib2nib/src/NSLayoutConstraint.h b/tools/vsimporter/xib2nib/src/NSLayoutConstraint.h index 29068d523b..950c95a328 100644 --- a/tools/vsimporter/xib2nib/src/NSLayoutConstraint.h +++ b/tools/vsimporter/xib2nib/src/NSLayoutConstraint.h @@ -27,6 +27,7 @@ enum { NSLayoutPriorityDefaultLow = 250, NSLayoutPriorityFittingSizeCompression = 50, }; + typedef float NSLayoutPriority; typedef enum { @@ -70,11 +71,14 @@ class NSLayoutConstraint : public ObjectConverterSwapper { int _firstAttribute; int _secondAttribute; int _relation; - float _multiplier; - float _priority; - float _constant; - float _symbolicConstant; + double _multiplier; + int _priority; + double _constant; + double _symbolicConstant; bool _hasSymbolicConstant; + const char* _layoutIdentifier; + bool _placeholder; + bool _exportDefaultValues; public: NSLayoutConstraint(); @@ -83,4 +87,6 @@ class NSLayoutConstraint : public ObjectConverterSwapper { virtual void InitFromStory(XIBObject* obj); virtual void Awaken(); virtual void ConvertStaticMappings(NIBWriter* writer, XIBObject* obj); -}; \ No newline at end of file +private: + XIBObject* substituteItemUnsupported(NIBWriter* writer, XIBObject* item); +}; diff --git a/tools/vsimporter/xib2nib/src/ObjectConverter.cpp b/tools/vsimporter/xib2nib/src/ObjectConverter.cpp index 02c15dd127..3ba8ac5588 100644 --- a/tools/vsimporter/xib2nib/src/ObjectConverter.cpp +++ b/tools/vsimporter/xib2nib/src/ObjectConverter.cpp @@ -21,6 +21,7 @@ #include "UIColor.h" #include "UIButton.h" #include "UIFont.h" +#include "UITextInputTraits.h" #include "UIRuntimeEventConnection.h" #include "UIRuntimeOutletConnection.h" #include "UIRuntimeOutletCollectionConnection.h" @@ -53,25 +54,30 @@ #include "UIPageControl.h" #include "UISwitch.h" #include "UISegmentedControl.h" +#include "UISegment.h" #include "UIDatePicker.h" #include "MKMapView.h" #include "UISlider.h" #include "NSLayoutConstraint.h" #include "UICollectionViewCell.h" #include "UICollectionView.h" +#include "UICollectionViewFlowLayout.h" #include "UICollectionViewController.h" #include "UIStepper.h" #include "_UILayoutGuide.h" +#include "UILayoutGuide.h" #include "UIPanGestureRecognizer.h" #include "UISwipeGestureRecognizer.h" #include "UITapGestureRecognizer.h" #include "UIStackView.h" #include "UIProgressView.h" #include "UIPongPressGestureRecognizer.h" +#include "UINibKeyValuePair.h" +#include #include -#include "..\WBITelemetry\WBITelemetry.h" +#include "../WBITelemetry/WBITelemetry.h" #define IS_CONVERTER(newinst, classnamevar, name, type) \ if (strcmp(classnamevar, name) == 0) { \ @@ -148,6 +154,7 @@ XIBObject* ObjectConverter::ConverterForStoryObject(const char* className, pugi: IS_CONVERTER(ret, className, "variation", XIBVariation) IS_CONVERTER(ret, className, "items", XIBArray) IS_CONVERTER(ret, className, "connections", XIBArray) + IS_CONVERTER(ret, className, "segments", XIBArray) IS_CONVERTER(ret, className, "string", XIBObjectString) IS_CONVERTER(ret, className, "viewController", UIViewController) IS_CONVERTER(ret, className, "splitViewController", UIViewController) @@ -168,6 +175,7 @@ XIBObject* ObjectConverter::ConverterForStoryObject(const char* className, pugi: IS_CONVERTER(ret, className, "outletCollection", UIRuntimeOutletCollectionConnection) IS_CONVERTER(ret, className, "segue", UIStoryboardSegue) IS_CONVERTER(ret, className, "fontDescription", UIFont) + IS_CONVERTER(ret, className, "textInputTraits", UITextInputTraits) IS_CONVERTER(ret, className, "tableViewController", UITableViewController) IS_CONVERTER(ret, className, "tableView", UITableView) IS_CONVERTER(ret, className, "tableViewCell", UITableViewCell) @@ -185,19 +193,25 @@ XIBObject* ObjectConverter::ConverterForStoryObject(const char* className, pugi: IS_CONVERTER(ret, className, "constraint", NSLayoutConstraint) IS_CONVERTER(ret, className, "layoutGuides", XIBVariation) IS_CONVERTER(ret, className, "viewControllerLayoutGuide", _UILayoutGuide) + IS_CONVERTER(ret, className, "viewLayoutGuide", UILayoutGuide) IS_CONVERTER(ret, className, "datePicker", UIDatePicker) IS_CONVERTER(ret, className, "slider", UISlider) IS_CONVERTER(ret, className, "collectionReusableView", UICollectionReusableView) IS_CONVERTER(ret, className, "collectionViewCell", UICollectionViewCell) IS_CONVERTER(ret, className, "collectionView", UICollectionView) + IS_CONVERTER(ret, className, "collectionViewFlowLayout", UICollectionViewFlowLayout) IS_CONVERTER(ret, className, "collectionViewController", UICollectionViewController) IS_CONVERTER(ret, className, "pickerView", UIPickerView) IS_CONVERTER(ret, className, "segmentedControl", UISegmentedControl) + IS_CONVERTER(ret, className, "segment", UISegment); IS_CONVERTER(ret, className, "stepper", UIStepper) IS_CONVERTER(ret, className, "panGestureRecognizer", UIPanGestureRecognizer) IS_CONVERTER(ret, className, "swipeGestureRecognizer", UISwipeGestureRecognizer) IS_CONVERTER(ret, className, "tapGestureRecognizer", UITapGestureRecognizer) IS_CONVERTER(ret, className, "window", UIWindow) + // support for user defined attributes (and IBInspectable) + IS_CONVERTER(ret, className, "userDefinedRuntimeAttribute", UINibKeyValuePair) + IS_CONVERTER(ret, className, "userDefinedRuntimeAttributes", XIBArray) // Stubbed mapping - full functionality is not provided but these stubs will unblock the import process IS_CONVERTER(ret, className, "pageControl", UIPageControl) @@ -207,6 +221,7 @@ XIBObject* ObjectConverter::ConverterForStoryObject(const char* className, pugi: IS_CONVERTER(ret, className, "pongPressGestureRecognizer", UIPongPressGestureRecognizer) IS_CONVERTER(ret, className, "customObject", ObjectConverterSwapper) + IS_CONVERTER(ret, className, "nil", XIBObjectNil) if (ret == NULL) { TELEMETRY_EVENT_DATA(L"UnRecognizedTag", className); @@ -242,13 +257,82 @@ void ConvertOffset(struct _PropertyMapper* prop, NIBWriter* writer, XIBObject* p void ObjectConverter::InitFromXIB(XIBObject* obj) { _connections = NULL; + _userDefinedAttributes = NULL; _connectedObjects = NULL; } void ObjectConverter::InitFromStory(XIBObject* obj) { setSelfHandled(); _connections = (XIBArray*)FindMemberClass("connections"); + _userDefinedAttributes = (XIBArray*)FindMemberClass("userDefinedRuntimeAttributes"); } void ObjectConverter::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { + if (_connections) { + std::map outletCollectionMap; + + for (int i = 0; i < _connections->count(); i++) { + XIBObject* curObj = _connections->objectAtIndex(i); + if (strcmp(curObj->_className, "segue") == 0) { + UIStoryboardSegue* segue = (UIStoryboardSegue*)curObj; + + UIRuntimeEventConnection* newEvent = new UIRuntimeEventConnection(); + newEvent->_label = "perform:"; + newEvent->_source = this; + newEvent->_destination = segue; + newEvent->_eventMask = 0x40; + writer->_connections->AddMember(NULL, newEvent); + writer->AddOutputObject(newEvent); + } else if (strcmp(curObj->_outputClassName, "UIRuntimeOutletConnection") == 0) { + UIRuntimeOutletConnection* cur = (UIRuntimeOutletConnection*)curObj; + + UIRuntimeOutletConnection* newOutlet = new UIRuntimeOutletConnection(); + newOutlet->_label = cur->_label; + newOutlet->_source = cur->_source; + newOutlet->_destination = cur->_destination; + writer->_connections->AddMember(NULL, newOutlet); + writer->AddOutputObject(newOutlet); + } else if (strcmp(curObj->_outputClassName, "UIRuntimeEventConnection") == 0) { + UIRuntimeEventConnection* cur = (UIRuntimeEventConnection*)curObj; + + UIRuntimeEventConnection* newOutlet = new UIRuntimeEventConnection(); + newOutlet->_label = cur->_label; + newOutlet->_source = cur->_source; + newOutlet->_destination = cur->_destination; + newOutlet->_eventMask = cur->_eventMask; + writer->_connections->AddMember(NULL, newOutlet); + writer->AddOutputObject(newOutlet); + } else if (strcmp(curObj->_outputClassName, "UIRuntimeOutletCollectionConnection") == 0) { + UIRuntimeOutletCollectionConnection* cur = (UIRuntimeOutletCollectionConnection*)curObj; + + UIRuntimeOutletCollectionConnection* collection = outletCollectionMap[cur->_label]; + if (!collection) { + collection = new UIRuntimeOutletCollectionConnection(); + collection->_label = cur->_label; + collection->_source = cur->_source; + collection->addDestinations(cur->_destinations); + collection->_collectionClassName = cur->_collectionClassName; + outletCollectionMap[cur->_label] = collection; + } else { + collection->addDestinations(cur->_destinations); + } + } else { + assert(0); + } + } + + // drop collections if any + for( const auto& entry : outletCollectionMap ) { + writer->_connections->AddMember(NULL, entry.second); + writer->AddOutputObject(entry.second); + } + } + + if (_userDefinedAttributes) { + for (int i = 0; i < _userDefinedAttributes->count(); i++) { + XIBObject *curObj = _userDefinedAttributes->objectAtIndex(i); + writer->_keyValuePairs->AddMember(NULL, curObj); + writer->AddOutputObject(curObj); + } + } } ObjectConverter* ObjectConverter::Clone() { return this; @@ -281,6 +365,15 @@ void ObjectConverterSwapper::InitFromStory(XIBObject* obj) { if (getAttrib("customClass")) { _swappedClassName = getAttrAndHandle("customClass"); + const char* module = NULL; + if (getAttrib("customModule")) + module = getAttrAndHandle("customModule"); + if (module) { + // its swift, mange class name with module + char buf[128]; // should be big enough + snprintf(buf, 128, "_TtC%zu%s%zu%s", strlen(module), module, strlen(_swappedClassName), _swappedClassName); + _swappedClassName = strdup(buf); + } } } @@ -294,42 +387,4 @@ void ObjectConverterSwapper::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj->AddOutputMember(writer, "UIClassName", new XIBObjectString(obj->_swappedClassName)); obj->_outputClassName = "UIClassSwapper"; } - - // Add outlets - if (_connectedObjects) { - for (int i = 0; i < _connectedObjects->count(); i++) { - XIBObject* curObj = (UIRuntimeOutletConnection*)_connectedObjects->objectAtIndex(i); - if (strcmp(curObj->_outputClassName, "UIRuntimeOutletConnection") == 0) { - UIRuntimeOutletConnection* cur = (UIRuntimeOutletConnection*)curObj; - - UIRuntimeOutletConnection* newOutlet = new UIRuntimeOutletConnection(); - newOutlet->_label = cur->_label; - newOutlet->_source = cur->_source; - newOutlet->_destination = cur->_destination; - writer->_connections->AddMember(NULL, newOutlet); - writer->AddOutputObject(newOutlet); - } else if (strcmp(curObj->_outputClassName, "UIRuntimeEventConnection") == 0) { - UIRuntimeEventConnection* cur = (UIRuntimeEventConnection*)curObj; - - UIRuntimeEventConnection* newOutlet = new UIRuntimeEventConnection(); - newOutlet->_label = cur->_label; - newOutlet->_source = cur->_source; - newOutlet->_destination = cur->_destination; - newOutlet->_eventMask = cur->_eventMask; - writer->_connections->AddMember(NULL, newOutlet); - writer->AddOutputObject(newOutlet); - } else if (strcmp(curObj->_outputClassName, "UIRuntimeOutletCollectionConnection") == 0) { - UIRuntimeOutletCollectionConnection* cur = (UIRuntimeOutletCollectionConnection*)curObj; - - UIRuntimeOutletCollectionConnection* newOutlet = new UIRuntimeOutletCollectionConnection(); - newOutlet->_label = cur->_label; - newOutlet->_source = cur->_source; - newOutlet->_destination = cur->_destination; - writer->_connections->AddMember(NULL, newOutlet); - writer->AddOutputObject(newOutlet); - } else { - assert(0); - } - } - } } diff --git a/tools/vsimporter/xib2nib/src/ObjectConverter.h b/tools/vsimporter/xib2nib/src/ObjectConverter.h index 0b95ec31cf..4dd4b7760a 100644 --- a/tools/vsimporter/xib2nib/src/ObjectConverter.h +++ b/tools/vsimporter/xib2nib/src/ObjectConverter.h @@ -26,8 +26,13 @@ typedef struct _PropertyMapper { class ObjectConverter : public XIBObject { public: XIBArray* _connections; + XIBArray* _userDefinedAttributes; XIBArray* _variations; + ObjectConverter() { + _connections = NULL; + _userDefinedAttributes = NULL; + }; virtual void InitFromXIB(XIBObject* obj); virtual void InitFromStory(XIBObject* obj); virtual void ConvertStaticMappings(NIBWriter* writer, XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UIBarButtonItem.cpp b/tools/vsimporter/xib2nib/src/UIBarButtonItem.cpp index 6543f0fe83..7775f2efd9 100644 --- a/tools/vsimporter/xib2nib/src/UIBarButtonItem.cpp +++ b/tools/vsimporter/xib2nib/src/UIBarButtonItem.cpp @@ -100,23 +100,6 @@ void UIBarButtonItem::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { if (_customView) { AddOutputMember(writer, "UICustomView", _customView); } - if (_connections) { - for (int i = 0; i < _connections->count(); i++) { - XIBObject* curObj = _connections->objectAtIndex(i); - if (strcmp(curObj->_className, "segue") == 0) { - UIStoryboardSegue* segue = (UIStoryboardSegue*)curObj; - - UIRuntimeEventConnection* newEvent = new UIRuntimeEventConnection(); - newEvent->_label = "perform:"; - newEvent->_source = this; - newEvent->_destination = segue; - writer->_connections->AddMember(NULL, newEvent); - writer->AddOutputObject(newEvent); - - // AddOutputMember(writer, "UIOutlet", refObj); - } - } - } ObjectConverterSwapper::ConvertStaticMappings(writer, obj); } diff --git a/tools/vsimporter/xib2nib/src/UIButton.cpp b/tools/vsimporter/xib2nib/src/UIButton.cpp index 50cd091831..15e32bc5ab 100644 --- a/tools/vsimporter/xib2nib/src/UIButton.cpp +++ b/tools/vsimporter/xib2nib/src/UIButton.cpp @@ -20,10 +20,11 @@ #include "UICustomResource.h" #include "UIRuntimeEventConnection.h" #include "UIFont.h" +#include "UILabel.h" #include void ConvertInsets(struct _PropertyMapper* prop, NIBWriter* writer, XIBObject* propObj, XIBObject* obj) { - EdgeInsets edgeInsets; + UIEdgeInsets edgeInsets; char szName[255]; sprintf(szName, "IBUI%sEdgeInsets.top", prop->nibName); @@ -176,39 +177,17 @@ void UIButton::WriteStatefulContent(NIBWriter* writer, XIBObject* obj) { } static PropertyMapper propertyMappings[] = { - "IBUIText", - "UIText", - NULL, - "IBUITextColor", - "UITextColor", - NULL, - "IBUIHighlightedColor", - "UIHighlightedColor", - NULL, - "IBUILineBreakMode", - "UILineBreakMode", - NULL, - "IBUIContentEdgeInsets.top", - "Content", - ConvertInsets, - "IBUITitleEdgeInsets.top", - "Title", - ConvertInsets, - "IBUIImageEdgeInsets.top", - "Image", - ConvertInsets, - "IBUITitleShadowOffset", - "TitleShadow", - ConvertOffset, - "IBUIShowsTouchWhenHighlighted", - "UIShowsTouchWhenHighlighted", - NULL, - "IBUIImage", - "UIImage", - NULL, - "IBUIBackgroundImage", - "UIBackgroundImage", - NULL, + {"IBUIText", "UIText", NULL}, + {"IBUITextColor", "UITextColor", NULL}, + {"IBUIHighlightedColor", "UIHighlightedColor", NULL}, + {"IBUILineBreakMode", "LineBreakMode", NULL}, + {"IBUIContentEdgeInsets.top", "Content", ConvertInsets}, + {"IBUITitleEdgeInsets.top", "Title", ConvertInsets}, + {"IBUIImageEdgeInsets.top", "Image", ConvertInsets}, + {"IBUITitleShadowOffset", "TitleShadow", ConvertOffset}, + {"IBUIShowsTouchWhenHighlighted", "UIShowsTouchWhenHighlighted", NULL}, + {"IBUIImage", "UIImage", NULL}, + {"IBUIBackgroundImage", "UIBackgroundImage", NULL}, }; static const int numPropertyMappings = sizeof(propertyMappings) / sizeof(PropertyMapper); @@ -216,6 +195,10 @@ UIButton::UIButton() { _buttonType = 0; _statefulContent = NULL; _font = NULL; + _tintColor = NULL; + + // default line break mode is middleTrucation + _lineBreakMode = UILineBreakModeMiddleTruncation; // Default is true for both of these, so no need to write to nib if that's the case _adjustsImageWhenHighlighted = true; @@ -234,16 +217,6 @@ void UIButton::InitFromXIB(XIBObject* obj) { obj->_outputClassName = "UIButton"; } -void PopulateInsetsFromStoryboard(XIBObject* obj, const char* insetType, EdgeInsets& insets) { - XIBObject* insetNode = obj->FindMemberAndHandle(const_cast(insetType)); - if (insetNode) { - insets.top = strtof(insetNode->getAttrAndHandle("minY"), NULL); - insets.left = strtof(insetNode->getAttrAndHandle("minX"), NULL); - insets.bottom = strtof(insetNode->getAttrAndHandle("maxY"), NULL); - insets.right = strtof(insetNode->getAttrAndHandle("maxX"), NULL); - } -} - void UIButton::InitFromStory(XIBObject* obj) { UIControl::InitFromStory(obj); @@ -260,6 +233,16 @@ void UIButton::InitFromStory(XIBObject* obj) { } _font = (UIFont*)obj->FindMemberAndHandle("fontDescription"); + _tintColor = (UIColor*)FindMemberAndHandle("tintColor"); + + const char* lineBreakModeAttributeValue = getAttrib("lineBreakMode"); + if (lineBreakModeAttributeValue) { + if (storyToUILineBreakMode.find(lineBreakModeAttributeValue) != storyToUILineBreakMode.end()) { + _lineBreakMode = storyToUILineBreakMode[lineBreakModeAttributeValue]; + } else { + printf("invalid linebreak value %s, using default (tailTruncation) \n", lineBreakModeAttributeValue); + } + } if (getAttrib("adjustsImageWhenDisabled")) { if (strcmp(getAttrAndHandle("adjustsImageWhenDisabled"), "NO") == 0) { @@ -274,9 +257,9 @@ void UIButton::InitFromStory(XIBObject* obj) { } // Insets - PopulateInsetsFromStoryboard(obj, "imageEdgeInsets", _imageEdgeInsets); - PopulateInsetsFromStoryboard(obj, "contentEdgeInsets", _contentEdgeInsets); - PopulateInsetsFromStoryboard(obj, "titleEdgeInsets", _titleEdgeInsets); + PopulateInsetsFromStoryboard("imageEdgeInsets", _imageEdgeInsets); + PopulateInsetsFromStoryboard("contentEdgeInsets", _contentEdgeInsets); + PopulateInsetsFromStoryboard("titleEdgeInsets", _titleEdgeInsets); obj->_outputClassName = "UIButton"; } @@ -291,14 +274,22 @@ void UIButton::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { obj->AddOutputMember(writer, "UIFont", _font); } - // Default is true, so no need to write to nib if that's the case - if (!_adjustsImageWhenHighlighted) { - AddBool(writer, "UIAdjustsImageWhenHighlighted", false); + if (_tintColor) { + AddOutputMember(writer, "UITintColor", _tintColor); + } + + if (_lineBreakMode != UILineBreakModeMiddleTruncation) { + AddInt(writer, "UILineBreakMode", _lineBreakMode); + } + + // Default in NIB is false, so no need to write to nib if that's the case + if (_adjustsImageWhenHighlighted) { + AddBool(writer, "UIAdjustsImageWhenHighlighted", true); } - // Default is true, so no need to write to nib if that's the case - if (!_adjustsImageWhenDisabled) { - AddBool(writer, "UIAdjustsImageWhenDisabled", false); + // Default in NIB is false, so no need to write to nib if that's the case + if (_adjustsImageWhenDisabled) { + AddBool(writer, "UIAdjustsImageWhenDisabled", true); } // Insets @@ -314,24 +305,6 @@ void UIButton::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { obj->AddData(writer, "UITitleEdgeInsets", _titleEdgeInsets); } - if (_connections) { - for (int i = 0; i < _connections->count(); i++) { - XIBObject* curObj = _connections->objectAtIndex(i); - - if (strcmp(curObj->_className, "segue") == 0) { - UIStoryboardSegue* segue = (UIStoryboardSegue*)curObj; - - UIRuntimeEventConnection* newEvent = new UIRuntimeEventConnection(); - newEvent->_label = "perform:"; - newEvent->_source = this; - newEvent->_destination = segue; - newEvent->_eventMask = 0x40; - writer->_connections->AddMember(NULL, newEvent); - writer->AddOutputObject(newEvent); - } - } - } - WriteStatefulContent(writer, this); UIControl::ConvertStaticMappings(writer, obj); } diff --git a/tools/vsimporter/xib2nib/src/UIButton.h b/tools/vsimporter/xib2nib/src/UIButton.h index 529f472594..03f9ab3e47 100644 --- a/tools/vsimporter/xib2nib/src/UIButton.h +++ b/tools/vsimporter/xib2nib/src/UIButton.h @@ -16,32 +16,22 @@ #pragma once #include "UIControl.h" +#include -struct EdgeInsets { - float top; - float left; - float bottom; - float right; - - EdgeInsets() : top(INFINITY), left(INFINITY), bottom(INFINITY), right(INFINITY) { - } - - bool IsValid() { - return top != INFINITY && left != INFINITY && bottom != INFINITY && right != INFINITY; - } -}; class UIFont; class UIButton : public UIControl { public: int _buttonType; UIFont* _font; + UIColor* _tintColor; XIBObject* _statefulContent; bool _adjustsImageWhenHighlighted; bool _adjustsImageWhenDisabled; - EdgeInsets _imageEdgeInsets; - EdgeInsets _contentEdgeInsets; - EdgeInsets _titleEdgeInsets; + UIEdgeInsets _imageEdgeInsets; + UIEdgeInsets _contentEdgeInsets; + UIEdgeInsets _titleEdgeInsets; + int _lineBreakMode; UIButton(); virtual void InitFromXIB(XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UICollectionView.cpp b/tools/vsimporter/xib2nib/src/UICollectionView.cpp index 9d760906ec..df9f599576 100644 --- a/tools/vsimporter/xib2nib/src/UICollectionView.cpp +++ b/tools/vsimporter/xib2nib/src/UICollectionView.cpp @@ -15,25 +15,32 @@ //****************************************************************************** #include "UICollectionView.h" +#include "UICollectionViewFlowLayout.h" UICollectionView::UICollectionView() { + _collectionViewLayout = NULL; } void UICollectionView::InitFromXIB(XIBObject* obj) { - UIView::InitFromXIB(obj); + UIScrollView::InitFromXIB(obj); obj->_outputClassName = "UICollectionView"; } void UICollectionView::InitFromStory(XIBObject* obj) { - UIView::InitFromStory(obj); + UIScrollView::InitFromStory(obj); + _collectionViewLayout = (UICollectionViewFlowLayout*)obj->FindMember("collectionViewLayout"); obj->_outputClassName = "UICollectionView"; } void UICollectionView::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { writer->_allUIObjects->AddMember(NULL, this); - UIView::ConvertStaticMappings(writer, obj); + + if (_collectionViewLayout) + AddOutputMember(writer , "UICollectionLayout", _collectionViewLayout); + + UIScrollView::ConvertStaticMappings(writer, obj); } ObjectConverter* UICollectionView::Clone() { diff --git a/tools/vsimporter/xib2nib/src/UICollectionView.h b/tools/vsimporter/xib2nib/src/UICollectionView.h index 2f10a0e2c2..6bf09b0b91 100644 --- a/tools/vsimporter/xib2nib/src/UICollectionView.h +++ b/tools/vsimporter/xib2nib/src/UICollectionView.h @@ -1,8 +1,13 @@ #pragma once -#include "UIView.h" -class UICollectionView : public UIView { +#include "UIScrollView.h" + +class UICollectionViewFlowLayout; + +class UICollectionView : public UIScrollView { private: public: + UICollectionViewFlowLayout *_collectionViewLayout; + UICollectionView(); virtual void InitFromXIB(XIBObject* obj); virtual void InitFromStory(XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UICollectionViewFlowLayout.cpp b/tools/vsimporter/xib2nib/src/UICollectionViewFlowLayout.cpp new file mode 100644 index 0000000000..9afb1d61ab --- /dev/null +++ b/tools/vsimporter/xib2nib/src/UICollectionViewFlowLayout.cpp @@ -0,0 +1,127 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#include "UICollectionViewFlowLayout.h" +#include + +typedef enum { + UISectionInsetReferenceContent = 0, + UISectionInsetReferenceSafeArea, + UISectionInsetReferenceLayoutMargins +} UISectionInsetReference; + +static std::map storyToInsetReference = { + { "safeArea", UISectionInsetReferenceSafeArea }, + { "layoutMargins", UISectionInsetReferenceLayoutMargins } +}; + +typedef enum { + UIScrollDirectionVertical = 0, + UIScrollDirectionHorizontal, +} UIScrollDirection; + +static std::map storyToScrollDirrection = { + { "vertical", UIScrollDirectionVertical }, + { "horizontal", UIScrollDirectionHorizontal } +}; + + +UICollectionViewFlowLayout::UICollectionViewFlowLayout() { + _scrollDirection = UIScrollDirectionVertical; + _minimumLineSpacing = -1; + _minimumInteritemSpacing = -1; + _customClass = NULL; + _customModule = NULL; + _sectionInsetReference = UISectionInsetReferenceContent; +} + +void UICollectionViewFlowLayout::InitFromXIB(XIBObject* obj) { + // Outdated code do nothing +} + +void UICollectionViewFlowLayout::InitFromStory(XIBObject* obj) { + obj->PopulateSizeFromStoryboard("itemSize", _itemSize); + obj->PopulateSizeFromStoryboard("headerReferenceSize", _headerReferenceSize); + obj->PopulateSizeFromStoryboard("footerReferenceSize", _footerReferenceSize); + obj->PopulateInsetsFromStoryboard("sectionInset", _sectionInset); + + _customClass = obj->getAttrAndHandle("customClass"); + if (_customClass) { + const char* module = obj->getAttrAndHandle("customModule");; + if (module) { + // its swift, mange class name with module + char buf[128]; // should be big enough + snprintf(buf, 128, "_TtC%zu%s%zu%s", strlen(module), module, strlen(_customClass), _customClass); + _customClass = strdup(buf); + } + } + + const char* attr; + if ((attr = obj->getAttrAndHandle("minimumLineSpacing"))) { + _minimumLineSpacing = strtof(attr, NULL); + } + + if ((attr = obj->getAttrAndHandle("minimumInteritemSpacing"))) { + _minimumInteritemSpacing = strtof(attr, NULL); + } + + if ((attr = obj->getAttrAndHandle("sectionInsetReference"))) { + if (storyToInsetReference.find(attr) != storyToInsetReference.end()) { + _sectionInsetReference = storyToInsetReference[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("scrollDirection"))) { + if (storyToScrollDirrection.find(attr) != storyToScrollDirrection.end()) { + _scrollDirection = storyToScrollDirrection[attr]; + } + } +} + +void UICollectionViewFlowLayout::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { + _outputClassName = "UICollectionViewFlowLayout"; + + if (_itemSize.IsValid()) + obj->AddData(writer, "UIItemSize", _itemSize); + + if (_headerReferenceSize.IsValid()) + obj->AddData(writer, "UIHeaderReferenceSize", _headerReferenceSize); + + if (_footerReferenceSize.IsValid()) + obj->AddData(writer, "UIFooterReferenceSize", _footerReferenceSize); + + if (_sectionInset.IsValid()) + obj->AddData(writer, "UISectionInset", _sectionInset); + + if (_customClass) { + obj->AddString(writer, "UIClassName", _customClass); + obj->AddString(writer, "UIOriginalClassName", "UICollectionViewLayout"); + } + + if (_minimumLineSpacing >= 0) + AddOutputMember(writer, "UILineSpacing", new XIBObjectFloat(_minimumLineSpacing)); + + if (_minimumInteritemSpacing >= 0) + AddOutputMember(writer, "UIInteritemSpacing", new XIBObjectFloat(_minimumInteritemSpacing)); + + if (_scrollDirection != UIScrollDirectionVertical) + AddInt(writer, "UIScrollDirection", _scrollDirection); + + if (_sectionInsetReference != UISectionInsetReferenceContent) + AddInt(writer, "UISectionInsetReference", _sectionInsetReference); + + ObjectConverter::ConvertStaticMappings(writer, obj); +} diff --git a/tools/vsimporter/xib2nib/src/UICollectionViewFlowLayout.h b/tools/vsimporter/xib2nib/src/UICollectionViewFlowLayout.h new file mode 100644 index 0000000000..c0857c8f05 --- /dev/null +++ b/tools/vsimporter/xib2nib/src/UICollectionViewFlowLayout.h @@ -0,0 +1,40 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#pragma once +#include "ObjectConverter.h" + + +class UICollectionViewFlowLayout : public ObjectConverter { +public: + int _scrollDirection; + float _minimumLineSpacing; + float _minimumInteritemSpacing; + + const char *_customClass; + const char *_customModule; + + int _sectionInsetReference; + CGSize _itemSize; + CGSize _headerReferenceSize; + CGSize _footerReferenceSize; + UIEdgeInsets _sectionInset; + + UICollectionViewFlowLayout(); + virtual void InitFromXIB(XIBObject* obj); + virtual void InitFromStory(XIBObject* obj); + virtual void ConvertStaticMappings(NIBWriter* writer, XIBObject* obj); +}; diff --git a/tools/vsimporter/xib2nib/src/UIColor.cpp b/tools/vsimporter/xib2nib/src/UIColor.cpp index 3510c62915..0f7bb1a5fb 100644 --- a/tools/vsimporter/xib2nib/src/UIColor.cpp +++ b/tools/vsimporter/xib2nib/src/UIColor.cpp @@ -129,15 +129,15 @@ void UIColor::InitFromStory(XIBObject* obj) { if (strcmp(space, "calibratedWhite") == 0) { _colorSpaceOut = colorSpaceWhite; - _white = strtod(getAttrAndHandle("white"), NULL); - _a = strtod(getAttrAndHandle("alpha"), NULL); + _white = strtof(getAttrAndHandle("white"), NULL); + _a = strtof(getAttrAndHandle("alpha"), NULL); } else if (strcmp(space, "calibratedRGB") == 0 || strcmp(space, "deviceRGB") == 0 || strcmp(space, "adobeRGB1998") == 0 || strcmp(space, "sRGB") == 0) { _colorSpaceOut = colorSpaceRGB; - _a = strtod(getAttrAndHandle("alpha"), NULL); - _r = strtod(getAttrAndHandle("red"), NULL); - _g = strtod(getAttrAndHandle("green"), NULL); - _b = strtod(getAttrAndHandle("blue"), NULL); + _a = strtof(getAttrAndHandle("alpha"), NULL); + _r = strtof(getAttrAndHandle("red"), NULL); + _g = strtof(getAttrAndHandle("green"), NULL); + _b = strtof(getAttrAndHandle("blue"), NULL); } else { spaceIsHandled = false; } @@ -152,19 +152,19 @@ void UIColor::InitFromStory(XIBObject* obj) { void UIColor::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { if (!_outputClassName) - _outputClassName = "UIColor"; + obj->_outputClassName = "UIColor"; if (!_isStory) { switch (_colorSpaceOut) { case colorSpaceRGB: case colorSpaceFull: if (_r == _g && _r == _b) { - AddOutputMember(writer, "UIWhite", new XIBObjectFloat(_r)); + obj->AddOutputMember(writer, "UIWhite", new XIBObjectFloat(_r)); } - AddOutputMember(writer, "UIRed", new XIBObjectFloat(_r)); - AddOutputMember(writer, "UIGreen", new XIBObjectFloat(_g)); - AddOutputMember(writer, "UIBlue", new XIBObjectFloat(_b)); - AddOutputMember(writer, "UIAlpha", new XIBObjectFloat(_a)); + obj->AddOutputMember(writer, "UIRed", new XIBObjectFloat(_r)); + obj->AddOutputMember(writer, "UIGreen", new XIBObjectFloat(_g)); + obj->AddOutputMember(writer, "UIBlue", new XIBObjectFloat(_b)); + obj->AddOutputMember(writer, "UIAlpha", new XIBObjectFloat(_a)); break; default: @@ -172,27 +172,45 @@ void UIColor::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { } if (_systemName) { - AddString(writer, "UISystemColorName", _systemName); - AddString(writer, "UIPatternSelector", _systemName); + obj->AddString(writer, "UISystemColorName", _systemName); + obj->AddString(writer, "UIPatternSelector", _systemName); } } else { switch (_colorSpaceOut) { - case colorSpaceWhite: - AddOutputMember(writer, "UIWhite", new XIBObjectFloat(_white)); - AddOutputMember(writer, "UIAlpha", new XIBObjectFloat(_a)); + case colorSpaceWhite: { + obj->AddOutputMember(writer, "UIWhite", new XIBObjectFloat(_white)); + obj->AddOutputMember(writer, "UIAlpha", new XIBObjectFloat(_a)); + char buf[128]; + if (_a != 1) + snprintf(buf, 128, "%.3f %.3f", _white, _a); + else + snprintf(buf, 128, "%.3f", _white); + obj->AddString(writer, "NSWhite", strdup(buf)); + obj->AddInt(writer, "NSColorSpace", 4); + obj->AddInt(writer, "UIColorComponentCount", 2); break; + } case colorSpaceRGB: - case colorSpaceFull: - AddOutputMember(writer, "UIAlpha", new XIBObjectFloat(_a)); - AddOutputMember(writer, "UIRed", new XIBObjectFloat(_r)); - AddOutputMember(writer, "UIGreen", new XIBObjectFloat(_g)); - AddOutputMember(writer, "UIBlue", new XIBObjectFloat(_b)); + case colorSpaceFull: { + obj->AddOutputMember(writer, "UIAlpha", new XIBObjectFloat(_a)); + obj->AddOutputMember(writer, "UIRed", new XIBObjectFloat(_r)); + obj->AddOutputMember(writer, "UIGreen", new XIBObjectFloat(_g)); + obj->AddOutputMember(writer, "UIBlue", new XIBObjectFloat(_b)); + char buf[128]; + if (_a != 1) + snprintf(buf, 128, "%.3f %.3f %.3f %.3f", _r, _g, _b, _a); + else + snprintf(buf, 128, "%.3f %.3f %.3f", _r, _g, _b); + obj->AddString(writer, "NSRGB", strdup(buf)); + obj->AddInt(writer, "NSColorSpace", 2); + obj->AddInt(writer, "UIColorComponentCount", 4); break; + } } if (_systemName) { - AddString(writer, "UISystemColorName", _systemName); + obj->AddString(writer, "UISystemColorName", _systemName); } } } diff --git a/tools/vsimporter/xib2nib/src/UIControl.cpp b/tools/vsimporter/xib2nib/src/UIControl.cpp index 6606499112..212dc3b998 100644 --- a/tools/vsimporter/xib2nib/src/UIControl.cpp +++ b/tools/vsimporter/xib2nib/src/UIControl.cpp @@ -19,6 +19,9 @@ UIControl::UIControl() { _contentVerticalAlignment = UIControlContentVerticalAlignmentTop; _contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + _enabled = true; + _selected = false; + _highlighted = false; } void UIControl::InitFromXIB(XIBObject* obj) { @@ -63,6 +66,22 @@ void UIControl::InitFromStory(XIBObject* obj) { } } + const char* attr; + if ((attr = obj->getAttrAndHandle("enabled"))) { + if (strcmp(attr, "NO") == 0) + _enabled = false; + } + + if ((attr = obj->getAttrAndHandle("selected"))) { + if (strcmp(attr, "YES") == 0) + _selected = true; + } + + if ((attr = obj->getAttrAndHandle("highlighted"))) { + if (strcmp(attr, "YES") == 0) + _highlighted = true; + } + _outputClassName = "UIControl"; } diff --git a/tools/vsimporter/xib2nib/src/UIControl.h b/tools/vsimporter/xib2nib/src/UIControl.h index 35bed0e000..7c0d3833ec 100644 --- a/tools/vsimporter/xib2nib/src/UIControl.h +++ b/tools/vsimporter/xib2nib/src/UIControl.h @@ -59,6 +59,9 @@ typedef enum { class UIControl : public UIView { public: int _contentVerticalAlignment, _contentHorizontalAlignment; + bool _enabled; + bool _selected; + bool _highlighted; UIControl(); virtual void InitFromXIB(XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UIImageView.cpp b/tools/vsimporter/xib2nib/src/UIImageView.cpp index 5dce559d30..c833131925 100644 --- a/tools/vsimporter/xib2nib/src/UIImageView.cpp +++ b/tools/vsimporter/xib2nib/src/UIImageView.cpp @@ -18,7 +18,7 @@ #include "UICustomResource.h" static PropertyMapper propertyMappings[] = { - "IBUIImage", "UIImage", NULL, + {"IBUIImage", "UIImage", NULL} }; static const int numPropertyMappings = sizeof(propertyMappings) / sizeof(PropertyMapper); diff --git a/tools/vsimporter/xib2nib/src/UILabel.cpp b/tools/vsimporter/xib2nib/src/UILabel.cpp index 848e878d2f..6b52deac68 100644 --- a/tools/vsimporter/xib2nib/src/UILabel.cpp +++ b/tools/vsimporter/xib2nib/src/UILabel.cpp @@ -29,11 +29,21 @@ static void WriteLayoutWidth(struct _PropertyMapper* prop, NIBWriter* writer, XI } static PropertyMapper propertyMappings[] = { - "IBUIShadowColor", "UIShadowColor", NULL, "IBUILineBreakMode", "UILineBreakMode", NULL, "preferredMaxLayoutWidth", - "UIPreferredMaxLayoutWidth", WriteLayoutWidth, + {"IBUIShadowColor", "UIShadowColor", NULL}, {"IBUILineBreakMode", "UILineBreakMode", NULL}, + {"preferredMaxLayoutWidth", "UIPreferredMaxLayoutWidth", WriteLayoutWidth}, }; static const int numPropertyMappings = sizeof(propertyMappings) / sizeof(PropertyMapper); +std::map storyToUILineBreakMode = { + { "wordWrap", UILineBreakModeWordWrap }, + { "characterWrap", UILineBreakModeCharacterWrap }, + { "clip", UILineBreakModeClip }, + { "headTruncation", UILineBreakModeHeadTruncation }, + { "tailTruncation", UILineBreakModeTailTruncation }, + { "middleTruncation", UILineBreakModeMiddleTruncation }, +}; + + UILabel::UILabel() { _text = NULL; _textAlignment = 0; @@ -46,7 +56,7 @@ UILabel::UILabel() { _font = NULL; // default line break mode is tailTrucation - _lineBreakMode = 4; + _lineBreakMode = UILineBreakModeTailTruncation; } void UILabel::InitFromXIB(XIBObject* obj) { @@ -97,24 +107,8 @@ void UILabel::InitFromStory(XIBObject* obj) { const char* lineBreakModeAttributeString = "lineBreakMode"; const char* lineBreakModeAttributeValue = getAttrib(lineBreakModeAttributeString); if (lineBreakModeAttributeValue) { - if (strcmp(lineBreakModeAttributeValue, "wordWrap") == 0) { - _lineBreakMode = 0; - getAttrAndHandle(lineBreakModeAttributeString); - } else if (strcmp(lineBreakModeAttributeValue, "characterWrap") == 0) { - _lineBreakMode = 1; - getAttrAndHandle(lineBreakModeAttributeString); - } else if (strcmp(lineBreakModeAttributeValue, "clip") == 0) { - _lineBreakMode = 2; - getAttrAndHandle(lineBreakModeAttributeString); - } else if (strcmp(lineBreakModeAttributeValue, "headTruncation") == 0) { - _lineBreakMode = 3; - getAttrAndHandle(lineBreakModeAttributeString); - } else if (strcmp(lineBreakModeAttributeValue, "tailTruncation") == 0) { - _lineBreakMode = 4; - getAttrAndHandle(lineBreakModeAttributeString); - } else if (strcmp(lineBreakModeAttributeValue, "middleTruncation") == 0) { - _lineBreakMode = 5; - getAttrAndHandle(lineBreakModeAttributeString); + if (storyToUILineBreakMode.find(lineBreakModeAttributeValue) != storyToUILineBreakMode.end()) { + _lineBreakMode = storyToUILineBreakMode[lineBreakModeAttributeValue]; } else { printf("invalid linebreak value %s, using default (tailTruncation) \n", lineBreakModeAttributeValue); } @@ -176,7 +170,7 @@ void UILabel::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { AddInt(writer, "UINumberOfLines", _numberOfLines); } - if (_lineBreakMode != 4) { + if (_lineBreakMode != UILineBreakModeTailTruncation) { AddInt(writer, "UILineBreakMode", _lineBreakMode); } @@ -185,8 +179,10 @@ void UILabel::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { } if (_minimumFontSize != -1.0f) { + AddBool(writer, "UIAdjustsFontSizeToFit", true); AddOutputMember(writer, "UIMinimumFontSize", new XIBObjectFloat(_minimumFontSize)); } else if (_minimumScaleFactor != -1.0f) { + AddBool(writer, "UIAdjustsFontSizeToFit", true); AddOutputMember(writer, "UIMinimumScaleFactor", new XIBObjectFloat(_minimumScaleFactor)); } else { AddBool(writer, "UIAdjustsFontSizeToFit", false); @@ -202,4 +198,4 @@ void UILabel::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { ObjectConverter* UILabel::Clone() { return new UILabel(); -} \ No newline at end of file +} diff --git a/tools/vsimporter/xib2nib/src/UILabel.h b/tools/vsimporter/xib2nib/src/UILabel.h index 2c113863fe..3c7e616895 100644 --- a/tools/vsimporter/xib2nib/src/UILabel.h +++ b/tools/vsimporter/xib2nib/src/UILabel.h @@ -16,10 +16,25 @@ #pragma once #include "UIView.h" +#include class UIColor; class UIFont; +// line break mode used in both UILabel and UIButton (possible other places as well) +typedef enum { + UILineBreakModeWordWrap = 0, + UILineBreakModeCharacterWrap, + UILineBreakModeClip, + UILineBreakModeHeadTruncation, + UILineBreakModeTailTruncation, + UILineBreakModeMiddleTruncation +} UILineBreakMode; + + +// helper map initialized in UILabel.cpp +extern std::map storyToUILineBreakMode; + class UILabel : public UIView { private: CGSize _shadowOffset; diff --git a/tools/vsimporter/xib2nib/src/UILayoutGuide.cpp b/tools/vsimporter/xib2nib/src/UILayoutGuide.cpp new file mode 100644 index 0000000000..a394824e37 --- /dev/null +++ b/tools/vsimporter/xib2nib/src/UILayoutGuide.cpp @@ -0,0 +1,89 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#include "UILayoutGuide.h" +#include "NSLayoutConstraint.h" +#include + +UILayoutGuide::UILayoutGuide() { + _systemConstraints = new XIBArray(); +} + +void UILayoutGuide::InitFromXIB(XIBObject* obj) { + // Outdated code do nothing +} + +void UILayoutGuide::InitFromStory(XIBObject* obj) { + _owningView = obj->_parent; + _outputClassName = "UILayoutGuide"; + + const char* key = getAttrib("key"); + if (key && strcmp(key, "safeArea") == 0) { + // handle today only safe area + NSLayoutConstraint* systemConstraintLeft = new NSLayoutConstraint(); + systemConstraintLeft->_firstItem = this; + systemConstraintLeft->_firstAttribute = NSLayoutAttributeLeft; + systemConstraintLeft->_secondItem = _owningView; + systemConstraintLeft->_secondAttribute = NSLayoutAttributeLeft; + systemConstraintLeft->_layoutIdentifier = "UIViewSafeAreaLayoutGuide-left"; + systemConstraintLeft->_outputClassName = "NSLayoutConstraint"; + systemConstraintLeft->_ignoreUIObject = true; + + NSLayoutConstraint* systemConstraintTop = new NSLayoutConstraint(); + systemConstraintTop->_firstItem = this; + systemConstraintTop->_firstAttribute = NSLayoutAttributeTop; + systemConstraintTop->_secondItem = _owningView; + systemConstraintTop->_secondAttribute = NSLayoutAttributeTop; + systemConstraintTop->_layoutIdentifier = "UIViewSafeAreaLayoutGuide-top"; + systemConstraintTop->_outputClassName = "NSLayoutConstraint"; + systemConstraintTop->_ignoreUIObject = true; + + NSLayoutConstraint* systemConstraintRight = new NSLayoutConstraint(); + systemConstraintRight->_firstItem = _owningView; + systemConstraintRight->_firstAttribute = NSLayoutAttributeRight; + systemConstraintRight->_secondItem = this; + systemConstraintRight->_secondAttribute = NSLayoutAttributeRight; + systemConstraintRight->_layoutIdentifier = "UIViewSafeAreaLayoutGuide-right"; + systemConstraintRight->_outputClassName = "NSLayoutConstraint"; + systemConstraintRight->_ignoreUIObject = true; + + NSLayoutConstraint* systemConstraintBottom = new NSLayoutConstraint(); + systemConstraintBottom->_firstItem = _owningView; + systemConstraintBottom->_firstAttribute = NSLayoutAttributeBottom; + systemConstraintBottom->_secondItem = this; + systemConstraintBottom->_secondAttribute = NSLayoutAttributeBottom; + systemConstraintBottom->_layoutIdentifier = "UIViewSafeAreaLayoutGuide-bottom"; + systemConstraintBottom->_outputClassName = "NSLayoutConstraint"; + systemConstraintBottom->_ignoreUIObject = true; + + _systemConstraints->AddMember(NULL, systemConstraintTop); + _systemConstraints->AddMember(NULL, systemConstraintLeft); + _systemConstraints->AddMember(NULL, systemConstraintRight); + _systemConstraints->AddMember(NULL, systemConstraintBottom); + } +} + +void UILayoutGuide::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { + obj->AddOutputMember(writer, "UILayoutGuideOwningView", _owningView); + if (_systemConstraints->count()) { + // its safeArea, don't know what to export other cases as Xcode doesn't support this yet as at v9.2 + obj->AddString(writer, "UILayoutGuideIdentifier", "UIViewSafeAreaLayoutGuide"); + obj->AddBool(writer, "UILayoutGuideOwningViewIsLocked", true); + obj->AddOutputMember(writer, "UILayoutGuideSystemConstraints", _systemConstraints); + } + + ObjectConverter::ConvertStaticMappings(writer, obj); +} diff --git a/tools/vsimporter/xib2nib/src/UILayoutGuide.h b/tools/vsimporter/xib2nib/src/UILayoutGuide.h new file mode 100644 index 0000000000..61381b165f --- /dev/null +++ b/tools/vsimporter/xib2nib/src/UILayoutGuide.h @@ -0,0 +1,28 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#pragma once +#include "ObjectConverter.h" +class UILayoutGuide : public ObjectConverter { +public: + XIBObject* _owningView; + XIBArray* _systemConstraints; + + UILayoutGuide(); + virtual void InitFromXIB(XIBObject* obj); + virtual void InitFromStory(XIBObject* obj); + virtual void ConvertStaticMappings(NIBWriter* writer, XIBObject* obj); +}; diff --git a/tools/vsimporter/xib2nib/src/UINibKeyValuePair.cpp b/tools/vsimporter/xib2nib/src/UINibKeyValuePair.cpp new file mode 100644 index 0000000000..e3c21007ad --- /dev/null +++ b/tools/vsimporter/xib2nib/src/UINibKeyValuePair.cpp @@ -0,0 +1,111 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#include +#include "UIProxyObject.h" +#include "UINibKeyValuePair.h" +#include "XIBObjectValue.h" +#include "XIBObject.h" + +UINibKeyValuePair::UINibKeyValuePair() { +} + +void UINibKeyValuePair::InitFromXIB(XIBObject* obj) { + ObjectConverter::InitFromXIB(obj); + // not interested much in outdated xcode +} + +void UINibKeyValuePair::InitFromStory(XIBObject* obj) { + ObjectConverter::InitFromStory(obj); + + _className = "UINibKeyValuePair"; + _outputClassName = "UINibKeyValuePair"; + + _keyPath = getAttrAndHandle("keyPath"); + const char* type = getAttrAndHandle("type"); + _source = _parent->_parent; + if (!type ) { + assert(0); // shall not happen + } else if (strcmp(type , "boolean") == 0) { + const char* str = getAttrAndHandle("value"); + _value = new XIBObjectNumber(strcmp(str, "YES") == 0); + } else if (strcmp(type , "string") == 0) { + const char* str = getAttrAndHandle("value"); + _value = new XIBObjectString(str); + } else if (strcmp(type , "number") == 0) { + XIBObject *obj = FindMemberAndHandle("value"); + const char *str = obj->getAttrAndHandle("value"); + if (strcmp(obj->_node.name(), "integer") == 0) { + _value = new XIBObjectNumber(strtoll(str, NULL, 0)); + } else if (strcmp(obj->_node.name(), "real") == 0) { + _value = new XIBObjectNumber(strtod(str, NULL)); + } else if (strcmp(obj->_node.name(), "float") == 0) { + _value = new XIBObjectNumber(strtof(str, NULL)); + } else if (strcmp(obj->_node.name(), "double") == 0) { + _value = new XIBObjectNumber(strtod(str, NULL)); + } else { + assert(0); // shall not happen + } + } else if (strcmp(type , "point") == 0) { + XIBObject *obj= FindMemberAndHandle("value"); + if (obj) { + UIPoint pt; + pt.x = static_cast(strtod(obj->getAttrAndHandle("x"), NULL)); + pt.y = static_cast(strtod(obj->getAttrAndHandle("y"), NULL)); + _value = new XIBObjectValue(pt); + } + } else if (strcmp(type , "size") == 0) { + XIBObject *obj= FindMemberAndHandle("value"); + if (obj) { + CGSize size; + size.width = static_cast(strtod(obj->getAttrAndHandle("width"), NULL)); + size.height = static_cast(strtod(obj->getAttrAndHandle("height"), NULL)); + _value = new XIBObjectValue(size); + } + } else if (strcmp(type , "rect") == 0) { + XIBObject *obj= FindMemberAndHandle("value"); + if (obj) { + UIRect rect; + rect.x = static_cast(strtod(obj->getAttrAndHandle("x"), NULL)); + rect.y = static_cast(strtod(obj->getAttrAndHandle("y"), NULL)); + rect.width = static_cast(strtod(obj->getAttrAndHandle("width"), NULL)); + rect.height = static_cast(strtod(obj->getAttrAndHandle("height"), NULL)); + _value = new XIBObjectValue(rect); + } + } else if (strcmp(type , "range") == 0) { + XIBObject *obj= FindMemberAndHandle("value"); + if (obj) { + NSRange range = {0}; + range.location = strtoll(obj->getAttrAndHandle("location"), NULL, 0); + range.length = strtoll(obj->getAttrAndHandle("length"), NULL, 0); + _value = new XIBObjectValue(range); + } + } else if (strcmp(type , "color") == 0) { + _value = FindMemberAndHandle("value"); + } else if (strcmp(type , "image") == 0) { + const char* str = getAttrAndHandle("value"); + _value = new XIBObjectString(str); + } else if (strcmp(type , "nil") == 0) { + _value = new XIBObjectNil(); + } +} + +void UINibKeyValuePair::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { + AddOutputMember(writer, "UIObject", _source); + AddString(writer, "UIKeyPath", _keyPath); + AddOutputMember(writer, "UIValue", _value); + ObjectConverter::ConvertStaticMappings(writer, obj); +} diff --git a/tools/vsimporter/xib2nib/src/UINibKeyValuePair.h b/tools/vsimporter/xib2nib/src/UINibKeyValuePair.h new file mode 100644 index 0000000000..c83c0f8c20 --- /dev/null +++ b/tools/vsimporter/xib2nib/src/UINibKeyValuePair.h @@ -0,0 +1,30 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#pragma once +#include "ObjectConverter.h" + +class UINibKeyValuePair : public ObjectConverter { +public: + const char* _keyPath; + XIBObject *_source; + XIBObject *_value; +public: + UINibKeyValuePair(); + virtual void InitFromXIB(XIBObject* obj); + virtual void InitFromStory(XIBObject* obj); + virtual void ConvertStaticMappings(NIBWriter* writer, XIBObject* obj); +}; diff --git a/tools/vsimporter/xib2nib/src/UIProxyObject.cpp b/tools/vsimporter/xib2nib/src/UIProxyObject.cpp index 4e6dbfe67d..8a4df8f15c 100644 --- a/tools/vsimporter/xib2nib/src/UIProxyObject.cpp +++ b/tools/vsimporter/xib2nib/src/UIProxyObject.cpp @@ -39,34 +39,6 @@ void UIProxyObject::InitFromStory(XIBObject* obj) { } void UIProxyObject::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { - // Add outlets - if (_connectedObjects) { - for (int i = 0; i < _connectedObjects->count(); i++) { - XIBObject* curObj = (UIRuntimeOutletConnection*)_connectedObjects->objectAtIndex(i); - if (strcmp(curObj->_outputClassName, "UIRuntimeOutletConnection") == 0) { - UIRuntimeOutletConnection* cur = (UIRuntimeOutletConnection*)curObj; - - UIRuntimeOutletConnection* newOutlet = new UIRuntimeOutletConnection(); - newOutlet->_label = cur->_label; - newOutlet->_source = cur->_source; - newOutlet->_destination = cur->_destination; - writer->_connections->AddMember(NULL, newOutlet); - writer->AddOutputObject(newOutlet); - } else if (strcmp(curObj->_outputClassName, "UIRuntimeEventConnection") == 0) { - UIRuntimeEventConnection* cur = (UIRuntimeEventConnection*)curObj; - - UIRuntimeEventConnection* newOutlet = new UIRuntimeEventConnection(); - newOutlet->_label = cur->_label; - newOutlet->_source = cur->_source; - newOutlet->_destination = cur->_destination; - newOutlet->_eventMask = cur->_eventMask; - writer->_connections->AddMember(NULL, newOutlet); - writer->AddOutputObject(newOutlet); - } else { - assert(0); - } - } - } writer->_allUIObjects->AddMember(NULL, obj); AddString(writer, "UIProxiedObjectIdentifier", _identifier); diff --git a/tools/vsimporter/xib2nib/src/UIRuntimeOutletCollectionConnection.cpp b/tools/vsimporter/xib2nib/src/UIRuntimeOutletCollectionConnection.cpp index c37d5bd2be..bb27ac7d68 100644 --- a/tools/vsimporter/xib2nib/src/UIRuntimeOutletCollectionConnection.cpp +++ b/tools/vsimporter/xib2nib/src/UIRuntimeOutletCollectionConnection.cpp @@ -21,6 +21,7 @@ UIRuntimeOutletCollectionConnection::UIRuntimeOutletCollectionConnection() { _outputClassName = "UIRuntimeOutletCollectionConnection"; _className = "UIRuntimeOutletCollectionConnection"; _collectionClassName = NULL; + _destinations = NULL; _addsToExisting = false; } @@ -30,7 +31,13 @@ void UIRuntimeOutletCollectionConnection::InitFromXIB(XIBObject* obj) { _outputClassName = "UIRuntimeOutletCollectionConnection"; _label = obj->GetString("label", NULL); _source = obj->FindMember("source"); - _destination = obj->FindMember("destination"); + XIBObject* destObj = obj->FindMember("destination"); + if (destObj) { + _destinations = new XIBArray(); + _destinations->_className = "NSMutableArray"; + _destinations->AddMember(NULL, destObj); + } + _collectionClassName = obj->GetString("cachedDesigntimeCollectionClassName", NULL); _addsToExisting = obj->GetBool("addsContentToExistingCollection", false); } @@ -49,7 +56,11 @@ void UIRuntimeOutletCollectionConnection::InitFromStory(XIBObject* obj) { _source = _parent->_parent; ObjectConverter* destObj = (ObjectConverter*)findReference(destId); - _destination = destObj; + if (destObj) { + _destinations = new XIBArray(); + _destinations->_className = "NSMutableArray"; + _destinations->AddMember(NULL, destObj); + } // Check if the destination property is part of our heirarchy XIBObject* curObj = this; @@ -70,7 +81,19 @@ void UIRuntimeOutletCollectionConnection::ConvertStaticMappings(NIBWriter* write ObjectConverter::ConvertStaticMappings(writer, obj); AddString(writer, "UILabel", _label); AddOutputMember(writer, "UISource", _source); - AddOutputMember(writer, "UIDestination", _destination); + AddOutputMember(writer, "UIDestination", _destinations); AddString(writer, "runtimeCollectionClassName", _collectionClassName); AddBool(writer, "addsContentToExistingCollection", _addsToExisting); } + +void UIRuntimeOutletCollectionConnection::addDestinations(XIBArray *objs) { + if (!objs || objs->count() == 0) + return; + if (!_destinations) { + _destinations = new XIBArray(); + _destinations->_className = "NSMutableArray"; + } + + for (int i = 0; i < objs->count(); i++) + _destinations->AddMember(NULL, objs->objectAtIndex(i)); +} diff --git a/tools/vsimporter/xib2nib/src/UIRuntimeOutletCollectionConnection.h b/tools/vsimporter/xib2nib/src/UIRuntimeOutletCollectionConnection.h index 20ad732bad..6e982c3b4c 100644 --- a/tools/vsimporter/xib2nib/src/UIRuntimeOutletCollectionConnection.h +++ b/tools/vsimporter/xib2nib/src/UIRuntimeOutletCollectionConnection.h @@ -19,13 +19,15 @@ class UIRuntimeOutletCollectionConnection : public ObjectConverter { public: const char* _label; - XIBObject *_source, *_destination; + XIBObject *_source; const char* _collectionClassName; bool _addsToExisting; public: + XIBArray *_destinations; UIRuntimeOutletCollectionConnection(); + void addDestinations(XIBArray* objs); virtual void InitFromXIB(XIBObject* obj); virtual void InitFromStory(XIBObject* obj); virtual void ConvertStaticMappings(NIBWriter* writer, XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UIScrollView.cpp b/tools/vsimporter/xib2nib/src/UIScrollView.cpp index 3052501f89..c6e00ced8c 100644 --- a/tools/vsimporter/xib2nib/src/UIScrollView.cpp +++ b/tools/vsimporter/xib2nib/src/UIScrollView.cpp @@ -25,24 +25,12 @@ static void InvertBool(struct _PropertyMapper* prop, NIBWriter* writer, XIBObjec } static PropertyMapper propertyMappings[] = { - "IBUIScrollEnabled", - "UIScrollDisabled", - InvertBool, - "IBUIDelaysContentTouches", - "UIDelaysContentTouches", - NULL, - "IBUIDelaysContentTouches", - "UIDelaysContentTouches", - NULL, - "IBUIPagingEnabled", - "UIPagingEnabled", - NULL, - "IBUIShowsHorizontalScrollIndicator", - "UIShowsHorizontalScrollIndicator", - NULL, - "IBUIShowsVerticalScrollIndicator", - "UIShowsVerticalScrollIndicator", - NULL, + {"IBUIScrollEnabled", "UIScrollDisabled", InvertBool}, + {"IBUIDelaysContentTouches", "UIDelaysContentTouches", NULL}, + {"IBUIDelaysContentTouches", "UIDelaysContentTouches", NULL}, + {"IBUIPagingEnabled", "UIPagingEnabled", NULL}, + {"IBUIShowsHorizontalScrollIndicator", "UIShowsHorizontalScrollIndicator", NULL}, + {"IBUIShowsVerticalScrollIndicator", "UIShowsVerticalScrollIndicator", NULL}, }; static const int numPropertyMappings = sizeof(propertyMappings) / sizeof(PropertyMapper); diff --git a/tools/vsimporter/xib2nib/src/UISegment.cpp b/tools/vsimporter/xib2nib/src/UISegment.cpp index b5c64b9d0d..284a52374d 100644 --- a/tools/vsimporter/xib2nib/src/UISegment.cpp +++ b/tools/vsimporter/xib2nib/src/UISegment.cpp @@ -15,16 +15,15 @@ //****************************************************************************** #include "UISegment.h" -#include "UIColor.h" +#include "UICustomResource.h" +#include -UISegment::UISegment(XIBObject* info, int style, int position, UIColor* tintColor) { - _info = info; - _style = style; - _position = position; - _tintColor = tintColor; +UISegment::UISegment() { _outputClassName = "UISegment"; - _connectedObjects = nullptr; - _connections = nullptr; + _title = NULL; + _image = NULL; + _enabled = true; + _position = 0; } void UISegment::InitFromXIB(XIBObject* obj) { @@ -36,17 +35,36 @@ void UISegment::InitFromXIB(XIBObject* obj) { void UISegment::InitFromStory(XIBObject* obj) { UIView::InitFromStory(obj); + _title = obj->getAttrAndHandle("title"); + _image = obj->getAttrAndHandle("image"); + const char* attr; + if ((attr = obj->getAttrAndHandle("enabled"))) { + if (strcmp(attr, "NO") == 0) + _enabled = false; + } + + PopulateSizeFromStoryboard("contentOffset", _contentOffset); + obj->_outputClassName = "UISegment"; } void UISegment::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { UIView::ConvertStaticMappings(writer, obj); - if (_info) - AddOutputMember(writer, "UISegmentInfo", _info); - if (_style) - AddInt(writer, "UISegmentStyle", _style); + if (_image) { + // add placeholder + UICustomResource *placeholder = new UICustomResource(); + placeholder->_imageName = strdup(_image); + AddOutputMember(writer, "UISegmentInfo", placeholder); + } else if (_title) { + AddString(writer, "UISegmentInfo", _title); + } + + if (!_enabled) + AddBool(writer, "UIUserInteractionDisabled", _enabled); + if (_position) AddInt(writer, "UISegmentPosition", _position); - if (_tintColor) - AddOutputMember(writer, "UISegmentTintColor", _tintColor); + + if (_contentOffset.IsValid()) + AddSize(writer, "UISegmentContentOffset", _contentOffset); } diff --git a/tools/vsimporter/xib2nib/src/UISegment.h b/tools/vsimporter/xib2nib/src/UISegment.h index 42692e54f3..daeface32e 100644 --- a/tools/vsimporter/xib2nib/src/UISegment.h +++ b/tools/vsimporter/xib2nib/src/UISegment.h @@ -17,15 +17,18 @@ #pragma once #include "UIView.h" -class UIColor; class UISegment : public UIView { public: - XIBObject* _info; - int _style; + const char* _title; + const char* _image; + CGSize _contentOffset; + bool _enabled; + + // is not parsed but to be set externaly int _position; - UIColor* _tintColor; - UISegment(XIBObject* info, int style, int position, UIColor* tintColor); + + UISegment(); virtual void InitFromXIB(XIBObject* obj); virtual void InitFromStory(XIBObject* obj); virtual void ConvertStaticMappings(NIBWriter* writer, XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UISegmentedControl.cpp b/tools/vsimporter/xib2nib/src/UISegmentedControl.cpp index 79cd6e63ee..0bfc5b52a5 100644 --- a/tools/vsimporter/xib2nib/src/UISegmentedControl.cpp +++ b/tools/vsimporter/xib2nib/src/UISegmentedControl.cpp @@ -21,52 +21,46 @@ UISegmentedControl::UISegmentedControl() { _segments = NULL; _momentary = false; + _springLoaded = false; _tintColor = NULL; - _style = 0; - _selected = -1; + _segmentControlStyle = 0; + _selectedSegmentIndex = -1; } void UISegmentedControl::InitFromXIB(XIBObject* obj) { UIControl::InitFromXIB(obj); + // removed outdated code +} - _momentary = obj->GetBool("IBMomentary", false); - - XIBArray* titles = (XIBArray*)obj->FindMember("IBSegmentTitles"); - XIBArray* widths = (XIBArray*)obj->FindMember("IBSegmentWidths"); - XIBArray* enabled = (XIBArray*)obj->FindMember("IBSegmentEnabledStates"); - XIBArray* images = (XIBArray*)obj->FindMember("IBSegmentImages"); - _tintColor = (UIColor*)obj->FindMember("IBTintColor"); - _style = obj->GetInt("IBSegmentControlStyle", 0); - _selected = obj->GetInt("IBSelectedSegmentIndex", -1); - - if (enabled) { - _segments = new XIBArray(); - UIRect curFrame = getFrame(); - float curX = 0.0f; - float frameWidth = curFrame.width - 5.0f; - float segWidth = frameWidth / (float)enabled->count(); - - for (int i = 0; i < enabled->count(); i++) { - bool segEnabled = enabled->objectAtIndex(i)->intValue(); - - XIBObject* title = titles->objectAtIndex(i); - UISegment* newSeg = new UISegment(title, _style, i == 0 ? 0 : i == enabled->count() - 1 ? 2 : 1, _tintColor); - newSeg->_ignoreUIObject = true; - - UIRect segFrame = curFrame; - segFrame.x = (float)i * segWidth; - // segFrame.width = +void UISegmentedControl::InitFromStory(XIBObject* obj) { + UIControl::InitFromStory(obj); - _segments->AddMember(NULL, newSeg); - _subviews->AddMember(NULL, newSeg); + _tintColor = (UIColor*)FindMemberAndHandle("tintColor"); + _segments = (XIBArray*)obj->FindMemberClass("segments"); + if (_segments) { + // add them to subviews also set proper index + for (int idx = 0; idx < _segments->count(); idx++) { + UISegment *segment = (UISegment*)_segments->objectAtIndex(idx); + segment->_position = idx; + + _subviews->AddMember(NULL, segment); } } - obj->_outputClassName = "UISegmentedControl"; -} + const char* attr; + if ((attr = obj->getAttrAndHandle("momentary"))) { + if (strcmp(attr, "YES") == 0) + _momentary = true; + } -void UISegmentedControl::InitFromStory(XIBObject* obj) { - UIControl::InitFromStory(obj); + if ((attr = obj->getAttrAndHandle("springLoaded"))) { + if (strcmp(attr, "YES") == 0) + _springLoaded = true; + } + + if ((attr = obj->getAttrAndHandle("selectedSegmentIndex"))) { + _selectedSegmentIndex = std::stoi(attr, NULL); + } obj->_outputClassName = "UISegmentedControl"; } @@ -77,10 +71,10 @@ void UISegmentedControl::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj AddOutputMember(writer, "UISegments", _segments); if (_momentary) AddBool(writer, "UIMomentary", _momentary); - if (_style) - AddInt(writer, "UISegmentedControlStyle", _style); - if (_selected != -1) - AddInt(writer, "UISelectedSegmentIndex", _selected); + if (_springLoaded) + AddBool(writer, "UISpringLoaded", _springLoaded); if (_tintColor) AddOutputMember(writer, "UISegmentedControlTintColor", _tintColor); + if (_selectedSegmentIndex != -1) + AddInt(writer, "UISelectedSegmentIndex", _selectedSegmentIndex); } diff --git a/tools/vsimporter/xib2nib/src/UISegmentedControl.h b/tools/vsimporter/xib2nib/src/UISegmentedControl.h index b14137538c..560ad627b4 100644 --- a/tools/vsimporter/xib2nib/src/UISegmentedControl.h +++ b/tools/vsimporter/xib2nib/src/UISegmentedControl.h @@ -21,9 +21,11 @@ class UISegmentedControl : public UIControl { public: XIBArray* _segments; bool _momentary; + bool _springLoaded; + UIColor* _tintColor; - int _style; - int _selected; + int _segmentControlStyle; + int _selectedSegmentIndex; UISegmentedControl(); virtual void InitFromXIB(XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UIStoryboardSegue.cpp b/tools/vsimporter/xib2nib/src/UIStoryboardSegue.cpp index 1e7230f850..096df46098 100644 --- a/tools/vsimporter/xib2nib/src/UIStoryboardSegue.cpp +++ b/tools/vsimporter/xib2nib/src/UIStoryboardSegue.cpp @@ -16,11 +16,13 @@ #include #include "UIStoryboardSegue.h" +#include "UIViewController.h" UIStoryboardSegue::UIStoryboardSegue() { _destination = NULL; _type = segueRelationship; _identifier = NULL; + _actionName = NULL; } void UIStoryboardSegue::InitFromXIB(XIBObject* obj) { @@ -44,11 +46,34 @@ void UIStoryboardSegue::InitFromStory(XIBObject* obj) { bool isHandled = true; if (strcmp(pKind, "modal") == 0) { _type = segueModal; + _outputClassName = "UIStoryboardModalSegueTemplate"; } else if (strcmp(pKind, "push") == 0) { _type = seguePush; + _outputClassName = "UIStoryboardPushSegueTemplate"; } else if (strcmp(pKind, "relationship") == 0) { _type = segueRelationship; + } else if (strcmp(pKind, "show") == 0) { + _type = segueShow; + _outputClassName = "UIStoryboardShowSegueTemplate"; + _actionName = "showViewController:sender:"; + } else if (strcmp(pKind, "showDetail") == 0) { + _type = segueShowDetails; + _outputClassName = "UIStoryboardShowSegueTemplate"; + _actionName = "showDetailViewController:sender:"; + } else if (strcmp(pKind, "presentation") == 0) { + _type = seguePresentModally; + _outputClassName = "UIStoryboardPresentationSegueTemplate"; + } else if (strcmp(pKind, "popoverPresentation") == 0) { + _type = seguePresentAsPopover; + _outputClassName = "UIStoryboardPopoverPresentationSegueTemplate"; + } else if (strcmp(pKind, "custom") == 0) { + _type = segueCustom; + _outputClassName = "UIStoryboardSegueTemplate"; + } else if (strcmp(pKind, "replace") == 0) { + _type = segueCustom; + _outputClassName = "UIStoryboardPushSegueTemplate"; } else { + _type = segueUnsupported; isHandled = false; } @@ -56,16 +81,20 @@ void UIStoryboardSegue::InitFromStory(XIBObject* obj) { getAttrAndHandle("kind"); } } - - if (_type == segueModal) { - _outputClassName = "UIStoryboardModalSegueTemplate"; - } else if (_type == seguePush) { - _outputClassName = "UIStoryboardPushSegueTemplate"; - } } void UIStoryboardSegue::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { ObjectConverter::ConvertStaticMappings(writer, obj); AddString(writer, "UIIdentifier", _identifier); - AddString(writer, "UIDestinationViewControllerIdentifier", _destination); + + // find story view controller by id and try to use it storyboardIdentifier if set as destination + XIBObject* controller = XIBObject::findReference(_destination); + UIViewController* uiViewController = dynamic_cast(controller); + if (uiViewController && uiViewController->_storyboardIdentifier) + AddString(writer, "UIDestinationViewControllerIdentifier", uiViewController->_storyboardIdentifier); + else + + AddString(writer, "UIDestinationViewControllerIdentifier", _destination); + if (_actionName != NULL) + AddString(writer, "UIActionName", _actionName); } diff --git a/tools/vsimporter/xib2nib/src/UIStoryboardSegue.h b/tools/vsimporter/xib2nib/src/UIStoryboardSegue.h index 64a288886f..48844a2308 100644 --- a/tools/vsimporter/xib2nib/src/UIStoryboardSegue.h +++ b/tools/vsimporter/xib2nib/src/UIStoryboardSegue.h @@ -17,13 +17,25 @@ #pragma once #include "ObjectConverter.h" -typedef enum { segueRelationship, segueModal, seguePush } SegueType; +typedef enum { + segueRelationship, + segueModal, // deprecated + seguePush, // deprecated + segueShow, + segueShowDetails, + seguePresentModally, + seguePresentAsPopover, + segueCustom, + + segueUnsupported, +} SegueType; class UIStoryboardSegue : public ObjectConverter { public: const char* _destination; SegueType _type; const char* _identifier; + const char* _actionName; UIStoryboardSegue(); virtual void InitFromXIB(XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UISwitch.cpp b/tools/vsimporter/xib2nib/src/UISwitch.cpp index e31bb8b1d6..21d6cc16f0 100644 --- a/tools/vsimporter/xib2nib/src/UISwitch.cpp +++ b/tools/vsimporter/xib2nib/src/UISwitch.cpp @@ -18,6 +18,7 @@ #include UISwitch::UISwitch() { + _on = false; } void UISwitch::InitFromXIB(XIBObject* obj) { @@ -29,9 +30,30 @@ void UISwitch::InitFromXIB(XIBObject* obj) { void UISwitch::InitFromStory(XIBObject* obj) { UIControl::InitFromStory(obj); + const char* attr; + if ((attr = obj->getAttrAndHandle("on"))) { + if (strcmp(attr, "YES") == 0) + _on = true; + } + _outputClassName = "UISwitch"; } void UISwitch::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { + if (_on) + AddBool(writer, "UISwitchOn", _on); + + if (_enabled) + AddBool(writer, "UISwitchEnabled", _enabled); + else + AddBool(writer, "UIDisabled", true); + + if (_selected) + AddBool(writer, "UISelected", _selected); + + if (_highlighted) + AddBool(writer, "UIHighlighted", _selected); + UIControl::ConvertStaticMappings(writer, obj); } + diff --git a/tools/vsimporter/xib2nib/src/UISwitch.h b/tools/vsimporter/xib2nib/src/UISwitch.h index 02de2674f2..e80238bb6a 100644 --- a/tools/vsimporter/xib2nib/src/UISwitch.h +++ b/tools/vsimporter/xib2nib/src/UISwitch.h @@ -18,6 +18,8 @@ #include "UIControl.h" class UISwitch : public UIControl { public: + bool _on; + UISwitch(); virtual void InitFromXIB(XIBObject* obj); virtual void InitFromStory(XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UITableView.cpp b/tools/vsimporter/xib2nib/src/UITableView.cpp index f6c9a6861b..3a01805f13 100644 --- a/tools/vsimporter/xib2nib/src/UITableView.cpp +++ b/tools/vsimporter/xib2nib/src/UITableView.cpp @@ -18,7 +18,7 @@ #include "UIColor.h" static PropertyMapper propertyMappings[] = { - "IBUIShowsSelectionImmediatelyOnTouchBegin", "UIShowsSelectionImmediatelyOnTouchBegin", NULL, + {"IBUIShowsSelectionImmediatelyOnTouchBegin", "UIShowsSelectionImmediatelyOnTouchBegin", NULL}, }; static const int numPropertyMappings = sizeof(propertyMappings) / sizeof(PropertyMapper); @@ -43,6 +43,7 @@ UITableView::UITableView() { _allowsSelectionDuringEditing = false; _separatorStyle = 0; _style = 0; + _rowHeight = -1; } void UITableView::InitFromXIB(XIBObject* obj) { @@ -71,6 +72,12 @@ void UITableView::InitFromStory(XIBObject* obj) { if (_footerView) { _subviews->AddMember(NULL, _footerView); } + + const char *attr; + if ((attr = obj->getAttrAndHandle("rowHeight"))) { + _rowHeight = strtof(attr, NULL); + } + obj->_outputClassName = "UITableView"; } @@ -92,4 +99,6 @@ void UITableView::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { AddOutputMember(writer, "UITableHeaderView", _headerView); if (_footerView) AddOutputMember(writer, "UITableFooterView", _footerView); + if (_rowHeight >= 0) + AddOutputMember(writer, "UIRowHeight", new XIBObjectFloat(_rowHeight)); } diff --git a/tools/vsimporter/xib2nib/src/UITableView.h b/tools/vsimporter/xib2nib/src/UITableView.h index aaee6666b7..7f4c7b7d2f 100644 --- a/tools/vsimporter/xib2nib/src/UITableView.h +++ b/tools/vsimporter/xib2nib/src/UITableView.h @@ -22,6 +22,7 @@ class UITableView : public UIScrollView { bool _allowsSelectionDuringEditing; int _style; int _separatorStyle; + float _rowHeight; UITableView(); virtual void Awaken(); virtual void InitFromXIB(XIBObject* obj); diff --git a/tools/vsimporter/xib2nib/src/UITableViewCell.cpp b/tools/vsimporter/xib2nib/src/UITableViewCell.cpp index 8b298cb338..31bf410dab 100644 --- a/tools/vsimporter/xib2nib/src/UITableViewCell.cpp +++ b/tools/vsimporter/xib2nib/src/UITableViewCell.cpp @@ -15,15 +15,39 @@ //****************************************************************************** #include "UITableViewCell.h" +#include + + +static std::map storyToSelectionStyle = { + { "none", UISelectionStyleNone }, + { "blue", UISelectionStyleBlue }, + { "gray", UISelectionStyleGray }, + { "default", UISelectionStyleDefault }}; + +static std::map storyToAccessoryType = { + { "disclosureIndicator", UIAccessoryTypeDisclosureIndicator }, + { "disclosureButton", UIAccessoryTypeDetailDisclosureButton }, + { "checkmark", UIAccessoryTypeCheckmark }, + { "detailButton", UIAccessoryTypeDetailButton }}; + +static std::map storyToCellStyle = { + { "IBUITableViewCellStyleDefault", UITableViewCellStyleBasic }, + { "IBUITableViewCellStyleValue1", UITableViewCellStyleRightDetails }, + { "IBUITableViewCellStyleValue2", UITableViewCellStyleLeftDetails }, + { "IBUITableViewCellStyleSubtitle", UITableViewCellStyleSubtitle }}; UITableViewCell::UITableViewCell() { _indentationLevel = 0; - _indentationWidth = 0; - _selectionStyle = 0; + _indentationWidth = 0.0f; + _selectionStyle = UISelectionStyleDefault; + _accessoryType = UIAccessoryTypeNone; + _editingAccessoryType = UIAccessoryTypeNone; + _cellStyle = UITableViewCellStyleCustom; _reuseIdentifier = NULL; _detailTextLabel = NULL; _imageView = NULL; _textLabel = NULL; + _focusStyleCustom = false; } void UITableViewCell::InitFromXIB(XIBObject* obj) { @@ -47,7 +71,44 @@ void UITableViewCell::InitFromStory(XIBObject* obj) { obj->_outputClassName = "UITableViewCell"; + const char* attr; + if ((attr = obj->getAttrAndHandle("style"))) { + if (storyToCellStyle.find(attr) != storyToCellStyle.end()) { + _cellStyle = storyToCellStyle[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("selectionStyle"))) { + if (storyToSelectionStyle.find(attr) != storyToSelectionStyle.end()) { + _selectionStyle = storyToSelectionStyle[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("editingAccessoryType"))) { + if (storyToAccessoryType.find(attr) != storyToAccessoryType.end()) { + _editingAccessoryType = storyToAccessoryType[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("accessoryType"))) { + if (storyToAccessoryType.find(attr) != storyToAccessoryType.end()) { + _accessoryType = storyToAccessoryType[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("indentationWidth"))) { + _indentationWidth = strtof(attr, NULL); + } + + if ((attr = obj->getAttrAndHandle("focusStyle"))) { + if (strcmp(attr, "custom") == 0) + _focusStyleCustom = true; + } + + _reuseIdentifier = obj->getAttrAndHandle("reuseIdentifier"); _contentView = (UIView*)obj->FindMemberAndHandle("contentView"); + if (_contentView) + _subviews->AddMember(NULL, _contentView); } void UITableViewCell::Awaken() { @@ -92,6 +153,16 @@ void UITableViewCell::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { obj->AddOutputMember(writer, "UITextLabel", _textLabel); if (_detailTextLabel) obj->AddOutputMember(writer, "UIDetailTextLabel", _detailTextLabel); + + if (_accessoryType != UIAccessoryTypeNone) + obj->AddInt(writer, "UIAccessoryType", _accessoryType); + if (_editingAccessoryType != UIAccessoryTypeNone) + obj->AddInt(writer, "UIEditingAccessoryType", _editingAccessoryType); + if (_cellStyle != UITableViewCellStyleCustom) + obj->AddInt(writer, "UITableViewCellStyle", _cellStyle); + if (_focusStyleCustom) + obj->AddInt(writer, "UIFocusStyle", 1); + obj->AddBool(writer, "UITableCellBackgroundColorSet", true); obj->AddInt(writer, "UISelectionStyle", _selectionStyle); } diff --git a/tools/vsimporter/xib2nib/src/UITableViewCell.h b/tools/vsimporter/xib2nib/src/UITableViewCell.h index 624308300b..e7c97af56d 100644 --- a/tools/vsimporter/xib2nib/src/UITableViewCell.h +++ b/tools/vsimporter/xib2nib/src/UITableViewCell.h @@ -16,6 +16,31 @@ #pragma once #include "UIView.h" + +typedef enum { + UISelectionStyleNone = 0, + UISelectionStyleBlue, + UISelectionStyleGray, + UISelectionStyleDefault, +} UISelectionStyle; + +typedef enum { + UIAccessoryTypeNone = 0, + UIAccessoryTypeDisclosureIndicator, + UIAccessoryTypeDetailDisclosureButton, + UIAccessoryTypeCheckmark, + UIAccessoryTypeDetailButton +} UIAccessoryType; + + +typedef enum { + UITableViewCellStyleCustom = 0, + UITableViewCellStyleBasic = UITableViewCellStyleCustom, + UITableViewCellStyleRightDetails, + UITableViewCellStyleLeftDetails, + UITableViewCellStyleSubtitle, +} UITableViewCellStyle; + class UITableViewCell : public UIView { private: const char* _reuseIdentifier; @@ -25,7 +50,10 @@ class UITableViewCell : public UIView { int _selectionStyle; int _indentationLevel; float _indentationWidth; - + int _accessoryType; + int _editingAccessoryType; + int _cellStyle; + bool _focusStyleCustom; public: UITableViewCell(); virtual void Awaken(); diff --git a/tools/vsimporter/xib2nib/src/UITextField.cpp b/tools/vsimporter/xib2nib/src/UITextField.cpp index 19f8bb30d4..1ac05b086b 100644 --- a/tools/vsimporter/xib2nib/src/UITextField.cpp +++ b/tools/vsimporter/xib2nib/src/UITextField.cpp @@ -17,6 +17,7 @@ #include "UITextField.h" #include "UIColor.h" #include "UIFont.h" +#include "UITextInputTraits.h" static void MakeMutable(struct _PropertyMapper* prop, NIBWriter* writer, XIBObject* propObj, XIBObject* obj) { propObj->_className = "NSMutableString"; @@ -33,30 +34,14 @@ static void WriteLayoutWidth(struct _PropertyMapper* prop, NIBWriter* writer, XI } static PropertyMapper propertyMappings[] = { - "IBUIHighlightedColor", - "UIHighlightedColor", - NULL, - "IBUIShadowColor", - "UIShadowColor", - NULL, - "IBUIBaselineAdjustment", - "UIBaselineAdjustment", - NULL, - "IBUIMinimumFontSize", - "UIMinimumFontSize", - WriteMinimumFontSize, - "IBUINumberOfLines", - "UINumberOfLines", - NULL, - "IBUITextAlignment", - "UITextAlignment", - NULL, - "IBUILineBreakMode", - "UILineBreakMode", - NULL, - "preferredMaxLayoutWidth", - "UIPreferredMaxLayoutWidth", - WriteLayoutWidth, + {"IBUIHighlightedColor", "UIHighlightedColor", NULL}, + {"IBUIShadowColor", "UIShadowColor", NULL}, + {"IBUIBaselineAdjustment", "UIBaselineAdjustment", NULL}, + {"IBUIMinimumFontSize", "UIMinimumFontSize", WriteMinimumFontSize}, + {"IBUINumberOfLines", "UINumberOfLines", NULL}, + {"IBUITextAlignment", "UITextAlignment", NULL}, + {"IBUILineBreakMode", "UILineBreakMode", NULL}, + {"preferredMaxLayoutWidth", "UIPreferredMaxLayoutWidth", WriteLayoutWidth}, }; static const int numPropertyMappings = sizeof(propertyMappings) / sizeof(PropertyMapper); @@ -68,8 +53,7 @@ UITextField::UITextField() { _placeholder = NULL; _borderStyle = 0; _font = NULL; - _autoCorrectionType = 0; - _returnKeyType = 0; + _textInputTraits = NULL; _clearsOnBeginEditing = false; _clearButtonOffset.width = 0.0f; _clearButtonOffset.height = 0.0f; @@ -88,12 +72,6 @@ void UITextField::InitFromXIB(XIBObject* obj) { _font = (UIFont*)obj->FindMember("IBUIFont"); } - XIBObject* inputTraits = obj->FindMember("IBUITextInputTraits"); - if (inputTraits) { - _autoCorrectionType = inputTraits->GetInt("IBUIAutocorrectionType", 0); - _returnKeyType = inputTraits->GetInt("IBUIReturnKeyType", 0); - } - _clearsOnBeginEditing = obj->GetBool("IBUIClearsOnBeginEditing", false); if (_clearsOnBeginEditing) { _clearButtonOffset.width = 3.0f; @@ -106,7 +84,7 @@ void UITextField::InitFromStory(XIBObject* obj) { UIControl::InitFromStory(obj); _font = (UIFont*)obj->FindMemberAndHandle("fontDescription"); - + _textInputTraits = (UITextInputTraits*)obj->FindMemberAndHandle("textInputTraits"); // This is default if borderStyle isn't present _borderStyle = 0; const char* borderStyle = obj->getAttrAndHandle("borderStyle"); @@ -156,12 +134,8 @@ void UITextField::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { obj->AddOutputMember(writer, "UITextColor", color->CreateObject(writer)); } - if (_autoCorrectionType) { - AddInt(writer, "UIAutocorrectionType", _autoCorrectionType); - } - - if (_returnKeyType) { - AddInt(writer, "UIReturnKeyType", _returnKeyType); + if (_textInputTraits) { + _textInputTraits->ConvertStaticMappings(writer, this); } if (_clearsOnBeginEditing) { diff --git a/tools/vsimporter/xib2nib/src/UITextField.h b/tools/vsimporter/xib2nib/src/UITextField.h index 81940fd986..3ce917f355 100644 --- a/tools/vsimporter/xib2nib/src/UITextField.h +++ b/tools/vsimporter/xib2nib/src/UITextField.h @@ -18,6 +18,7 @@ #include "UIControl.h" class UIFont; +class UITextInputTraits; class UITextField : public UIControl { private: @@ -27,8 +28,7 @@ class UITextField : public UIControl { int _borderStyle; XIBObject* _textColor; UIFont* _font; - int _autoCorrectionType; - int _returnKeyType; + UITextInputTraits* _textInputTraits; bool _clearsOnBeginEditing; CGSize _clearButtonOffset; diff --git a/tools/vsimporter/xib2nib/src/UITextInputTraits.cpp b/tools/vsimporter/xib2nib/src/UITextInputTraits.cpp new file mode 100644 index 0000000000..2bd8caca8d --- /dev/null +++ b/tools/vsimporter/xib2nib/src/UITextInputTraits.cpp @@ -0,0 +1,192 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#include "UITextInputTraits.h" +#include +#include + +static std::map storyToReturnType = { + { "go", UIReturnKeyTypeGo }, + { "google", UIReturnKeyTypeGoogle }, + { "join", UIReturnKeyTypeJoin }, + { "next", UIReturnKeyTypeNext }, + { "route", UIReturnKeyTypeRoute }, + { "search", UIReturnKeyTypeSearch }, + { "send", UIReturnKeyTypeSend }, + { "yahoo", UIReturnKeyTypeYahoo }, + { "done", UIReturnKeyTypeDone }, + { "emergencyCall", UIReturnKeyTypeEmergencyCall }, + { "continue", UIReturnKeyTypeContinue } +}; + +static std::map storyToAutocapitalizationType = { + { "words", UIAutocapitalizationTypeWords }, + { "sentences", UIAutocapitalizationTypeSentences }, + { "allCharacters", UIAutocapitalizationTypeAllCharacters } +}; + +typedef enum { + GenericBooleanOptionDefault = 0, + GenericBooleanOptionNo = 1, + GenericBooleanOptionYes = 2 +} GenericBooleanOption; + +static std::map storyToGenericBooleanOption = { + { "no", GenericBooleanOptionNo }, + { "yes", GenericBooleanOptionYes }, + // just in case also capitalized + { "NO", GenericBooleanOptionNo }, + { "YES", GenericBooleanOptionYes }, +}; + +static std::map storyToKeyboardAppearance = { + { "alert", UIKeyboardAppearanceAlert }, + { "light", UIKeyboardAppearanceLight } +}; + +static std::map storyToKeyboardType = { + { "alphabet", UIKeyboardTypeAlphabet }, + { "numbersAndPunctuation", UIKeyboardTypeNumbersAndPunctuation }, + { "URL", UIKeyboardTypeURL }, + { "numberPad", UIKeyboardTypeNumberPad }, + { "phonePad", UIKeyboardTypePhonePad }, + { "namePhonePad", UIKeyboardTypeNamePhonePad }, + { "emailAddress", UIKeyboardTypeEmailAddress }, + { "decimalPad", UIKeyboardTypeDecimalPad }, + { "twitter", UIKeyboardTypeTwitter }, + { "webSearch", UIKeyboardTypeWebSearch }, + { "ASCIICapableNumberPad", UIKeyboardTypeASCIICapableNumberPad } +}; + + +UITextInputTraits::UITextInputTraits() { + _returnKeyType = UIReturnKeyTypeDefault; + _textContentType = NULL; + _autocapitalizationType = UIAutocapitalizationTypeNone; + _autocorrectionType = GenericBooleanOptionDefault; + _smartDashesType = GenericBooleanOptionDefault; + _smartInsertDeleteType = GenericBooleanOptionDefault; + _smartQuotesType = GenericBooleanOptionDefault; + _spellCheckingType = GenericBooleanOptionDefault; + _keyboardType = UIKeyboardTypeDefault; + _keyboardAppearance = UIKeyboardAppearanceDefault; + _secureTextEntry = false; +} + +void UITextInputTraits::InitFromXIB(XIBObject* obj) { + // Outdated code do nothing +} + +void UITextInputTraits::InitFromStory(XIBObject* obj) { + const char *attr; + if ((attr = obj->getAttrAndHandle("returnKeyType"))) { + if (storyToReturnType.find(attr) != storyToReturnType.end()) { + _returnKeyType = storyToReturnType[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("autocapitalizationType"))) { + if (storyToAutocapitalizationType.find(attr) != storyToAutocapitalizationType.end()) { + _autocapitalizationType = storyToAutocapitalizationType[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("autocorrectionType"))) { + if (storyToGenericBooleanOption.find(attr) != storyToGenericBooleanOption.end()) { + _autocorrectionType = storyToGenericBooleanOption[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("smartDashesType"))) { + if (storyToGenericBooleanOption.find(attr) != storyToGenericBooleanOption.end()) { + _smartDashesType = storyToGenericBooleanOption[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("smartInsertDeleteType"))) { + if (storyToGenericBooleanOption.find(attr) != storyToGenericBooleanOption.end()) { + _smartInsertDeleteType = storyToGenericBooleanOption[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("smartQuotesType"))) { + if (storyToGenericBooleanOption.find(attr) != storyToGenericBooleanOption.end()) { + _smartQuotesType = storyToGenericBooleanOption[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("spellCheckingType"))) { + if (storyToGenericBooleanOption.find(attr) != storyToGenericBooleanOption.end()) { + _spellCheckingType = storyToGenericBooleanOption[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("keyboardType"))) { + if (storyToKeyboardType.find(attr) != storyToKeyboardType.end()) { + _keyboardType = storyToKeyboardType[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("keyboardAppearance"))) { + if (storyToKeyboardAppearance.find(attr) != storyToKeyboardAppearance.end()) { + _keyboardAppearance = storyToKeyboardAppearance[attr]; + } + } + + if ((attr = obj->getAttrAndHandle("secureTextEntry"))) { + if (strcmp(attr, "YES") == 0) { + _secureTextEntry = true; + } + } + + _textContentType = obj->getAttrAndHandle("textContentType"); +} + +void UITextInputTraits::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { + if (_returnKeyType != UIReturnKeyTypeDefault) + obj->AddInt(writer, "UIReturnKeyType", _returnKeyType); + + if (_autocapitalizationType != UIAutocapitalizationTypeNone) + obj->AddInt(writer, "UIAutocapitalizationType", _autocapitalizationType); + + if (_autocorrectionType != GenericBooleanOptionDefault) + obj->AddInt(writer, "UIAutocorrectionType", _autocorrectionType); + + if (_smartDashesType != GenericBooleanOptionDefault) + obj->AddInt(writer, "UITextSmartDashesType", _smartDashesType); + + if (_smartInsertDeleteType != GenericBooleanOptionDefault) + obj->AddInt(writer, "UITextSmartInsertDeleteType", _smartInsertDeleteType); + + if (_smartQuotesType != GenericBooleanOptionDefault) + obj->AddInt(writer, "UITextSmartQuotesType", _smartQuotesType); + + // TODO: seems as spellCheckingType is not get out for iOS nib + // if (_spellCheckingType != GenericBooleanOptionDefault) + // obj->AddInt(writer, "UI????Type", _spellCheckingType); + + if (_keyboardType != UIKeyboardTypeDefault) + obj->AddInt(writer, "UIKeyboardType", _keyboardType); + + if (_keyboardAppearance != UIKeyboardAppearanceDefault) + obj->AddInt(writer, "UIKeyboardAppearance", _keyboardAppearance); + + if (_secureTextEntry) + obj->AddBool(writer, "UISecureTextEntry", _secureTextEntry); + + if (_textContentType) + obj->AddString(writer, "UITextContentType", _textContentType); +} diff --git a/tools/vsimporter/xib2nib/src/UITextInputTraits.h b/tools/vsimporter/xib2nib/src/UITextInputTraits.h new file mode 100644 index 0000000000..9060aa1d92 --- /dev/null +++ b/tools/vsimporter/xib2nib/src/UITextInputTraits.h @@ -0,0 +1,81 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#pragma once +#include "ObjectConverter.h" + +typedef enum { + UIReturnKeyTypeDefault = 0, + UIReturnKeyTypeGo, + UIReturnKeyTypeGoogle, + UIReturnKeyTypeJoin, + UIReturnKeyTypeNext, + UIReturnKeyTypeRoute, + UIReturnKeyTypeSearch, + UIReturnKeyTypeSend, + UIReturnKeyTypeYahoo, + UIReturnKeyTypeDone, + UIReturnKeyTypeEmergencyCall, + UIReturnKeyTypeContinue +} UIReturnKeyType; + +typedef enum { + UIAutocapitalizationTypeNone = 0, + UIAutocapitalizationTypeWords, + UIAutocapitalizationTypeSentences, + UIAutocapitalizationTypeAllCharacters, +} UIAutocapitalizationType; + +typedef enum { + UIKeyboardTypeDefault = 0, + UIKeyboardTypeAlphabet, + UIKeyboardTypeNumbersAndPunctuation, + UIKeyboardTypeURL, + UIKeyboardTypeNumberPad, + UIKeyboardTypePhonePad, + UIKeyboardTypeNamePhonePad, + UIKeyboardTypeEmailAddress, + UIKeyboardTypeDecimalPad, + UIKeyboardTypeTwitter, + UIKeyboardTypeWebSearch, + UIKeyboardTypeASCIICapableNumberPad +} UIKeyboardType; + +typedef enum { + UIKeyboardAppearanceDefault = 0, + UIKeyboardAppearanceAlert, + UIKeyboardAppearanceLight +} UIKeyboardAppearance; + +class UITextInputTraits : public ObjectConverter { +public: + int _returnKeyType; + const char *_textContentType; + int _autocapitalizationType; + int _autocorrectionType; + int _smartDashesType; + int _smartInsertDeleteType; + int _smartQuotesType; + int _spellCheckingType; + int _keyboardType; + int _keyboardAppearance; + bool _secureTextEntry; + + UITextInputTraits(); + virtual void InitFromXIB(XIBObject* obj); + virtual void InitFromStory(XIBObject* obj); + virtual void ConvertStaticMappings(NIBWriter* writer, XIBObject* obj); +}; diff --git a/tools/vsimporter/xib2nib/src/UITextView.cpp b/tools/vsimporter/xib2nib/src/UITextView.cpp index 48b405f876..83c33c1884 100644 --- a/tools/vsimporter/xib2nib/src/UITextView.cpp +++ b/tools/vsimporter/xib2nib/src/UITextView.cpp @@ -33,30 +33,14 @@ static void WriteLayoutWidth(struct _PropertyMapper* prop, NIBWriter* writer, XI } static PropertyMapper propertyMappings[] = { - "IBUIHighlightedColor", - "UIHighlightedColor", - NULL, - "IBUIShadowColor", - "UIShadowColor", - NULL, - "IBUIBaselineAdjustment", - "UIBaselineAdjustment", - NULL, - "IBUIMinimumFontSize", - "UIMinimumFontSize", - WriteMinimumFontSize, - "IBUINumberOfLines", - "UINumberOfLines", - NULL, - "IBUITextAlignment", - "UITextAlignment", - NULL, - "IBUILineBreakMode", - "UILineBreakMode", - NULL, - "preferredMaxLayoutWidth", - "UIPreferredMaxLayoutWidth", - WriteLayoutWidth, + {"IBUIHighlightedColor", "UIHighlightedColor", NULL}, + {"IBUIShadowColor", "UIShadowColor", NULL}, + {"IBUIBaselineAdjustment", "UIBaselineAdjustment", NULL}, + {"IBUIMinimumFontSize", "UIMinimumFontSize", WriteMinimumFontSize}, + {"IBUINumberOfLines", "UINumberOfLines", NULL}, + {"IBUITextAlignment", "UITextAlignment", NULL}, + {"IBUILineBreakMode", "UILineBreakMode", NULL}, + {"preferredMaxLayoutWidth", "UIPreferredMaxLayoutWidth", WriteLayoutWidth}, }; static const int numPropertyMappings = sizeof(propertyMappings) / sizeof(PropertyMapper); @@ -99,7 +83,7 @@ void UITextView::InitFromStory(XIBObject* obj) { // InitFromStory is called on it XIBObject* textNode = (XIBObject*)obj->FindMemberAndHandle("text"); if (textNode) { - _text = _strdup(textNode->_node.text().as_string()); + _text = strdup(textNode->_node.text().as_string()); } _font = (UIFont*)obj->FindMemberAndHandle("fontDescription"); diff --git a/tools/vsimporter/xib2nib/src/UITextView.h b/tools/vsimporter/xib2nib/src/UITextView.h index dc311759b4..b359b5a656 100644 --- a/tools/vsimporter/xib2nib/src/UITextView.h +++ b/tools/vsimporter/xib2nib/src/UITextView.h @@ -36,5 +36,5 @@ class UITextView : public UIScrollView { UITextView(); virtual void InitFromXIB(XIBObject* obj); virtual void ConvertStaticMappings(NIBWriter* writer, XIBObject* obj); - virtual void UITextView::InitFromStory(XIBObject* obj); + virtual void InitFromStory(XIBObject* obj); }; diff --git a/tools/vsimporter/xib2nib/src/UIView.cpp b/tools/vsimporter/xib2nib/src/UIView.cpp index 62696873ca..9b4f3426cd 100644 --- a/tools/vsimporter/xib2nib/src/UIView.cpp +++ b/tools/vsimporter/xib2nib/src/UIView.cpp @@ -19,7 +19,10 @@ #include #include #include +#include #include "UIRuntimeOutletCollectionConnection.h" +#include "UILayoutGuide.h" +#include "NSLayoutConstraint.h" static void InvertBool(struct _PropertyMapper* prop, NIBWriter* writer, XIBObject* propObj, XIBObject* obj) { XIBObjectBool* value = (XIBObjectBool*)propObj; @@ -30,16 +33,21 @@ static void InvertBool(struct _PropertyMapper* prop, NIBWriter* writer, XIBObjec } static PropertyMapper propertyMappings[] = { - "IBUIUserInteractionEnabled", "UIUserInteractionDisabled", InvertBool, "IBUITag", "UITag", NULL, "IBUIAlpha", "UIAlpha", NULL, + {"IBUIUserInteractionEnabled", "UIUserInteractionDisabled", InvertBool}, + {"IBUITag", "UITag", NULL}, + {"IBUIAlpha", "UIAlpha", NULL}, }; static const int numPropertyMappings = sizeof(propertyMappings) / sizeof(PropertyMapper); +enum { + NSContentHugginPriorityDefault = 250, + NSContentCompressionResistancePriorityDefault = 750 +}; + UIView::UIView() { - memset(&_bounds, 0, sizeof(_bounds)); - memset(&_center, 0, sizeof(_center)); - memset(&_contentStretch, 0, sizeof(_contentStretch)); _subviews = new XIBArray(); _constraints = new XIBArray(); + _layoutGuides = new XIBArray(); _hidden = false; _opaque = true; _autoresizeSubviews = true; @@ -53,10 +61,10 @@ UIView::UIView() { _enabled = true; _translatesAutoresizeToConstraints = true; _tag = -1; - _horizontalHuggingPriority = -1.0; - _verticalHuggingPriority = -1.0; - _horizontalCompressionResistancePriority = -1.0; - _verticalCompressionResistancePriority = -1.0; + _horizontalHuggingPriority = NSContentHugginPriorityDefault; + _verticalHuggingPriority = NSContentHugginPriorityDefault; + _horizontalCompressionResistancePriority = NSContentCompressionResistancePriorityDefault; + _verticalCompressionResistancePriority = NSContentCompressionResistancePriorityDefault; } void UIView::InitFromXIB(XIBObject* obj) { @@ -72,7 +80,7 @@ void UIView::InitFromXIB(XIBObject* obj) { _bounds.height = 0; _center.x = 0; _center.y = 0; - sscanf(pszFramePos, "{{%f, %f}, {%f, %f}}", &_center.x, &_center.y, &_bounds.width, &_bounds.height); + sscanf(pszFramePos, "{{%lf, %lf}, {%lf, %lf}}", &_center.x, &_center.y, &_bounds.width, &_bounds.height); _center.x += _bounds.width / 2.0f; _center.y += _bounds.height / 2.0f; } else { @@ -81,7 +89,7 @@ void UIView::InitFromXIB(XIBObject* obj) { _bounds.y = 0; _bounds.width = 0; _bounds.height = 0; - sscanf(pszFramePos, "{%f, %f}", &_bounds.width, &_bounds.height); + sscanf(pszFramePos, "{%lf, %lf}", &_bounds.width, &_bounds.height); _center.x = _bounds.width / 2.0f; _center.y = _bounds.height / 2.0f; } @@ -136,6 +144,11 @@ void UIView::InitFromStory(XIBObject* obj) { _constraints = new XIBArray(); } + UILayoutGuide *safeAreaGuide = (UILayoutGuide*)FindMemberAndHandle("safeArea"); + if (safeAreaGuide) { + _layoutGuides->AddMember(NULL, safeAreaGuide); + } + if (getAttrib("tag")) { _tag = static_cast(strtod(getAttrAndHandle("tag"), NULL)); } @@ -212,19 +225,15 @@ void UIView::InitFromStory(XIBObject* obj) { _hidden = true; } } - XIBObject* frameRect = FindMemberAndHandle("frame"); - if (frameRect) { + PopulateRectFromStoryboard("frame", _bounds); + PopulateRectFromStoryboard("contentStretch", _contentStretch); + if (_bounds.IsValid()) { + _center.x = _bounds.x + _bounds.width / 2.0f; + _center.y = _bounds.y + _bounds.height / 2.0f; + _bounds.x = 0; _bounds.y = 0; - _bounds.width = static_cast(strtod(frameRect->getAttrAndHandle("width"), NULL)); - _bounds.height = static_cast(strtod(frameRect->getAttrAndHandle("height"), NULL)); - - _center.x = static_cast(strtod(frameRect->getAttrAndHandle("x"), NULL)); - _center.y = static_cast(strtod(frameRect->getAttrAndHandle("y"), NULL)); - - _center.x += _bounds.width / 2.0f; - _center.y += _bounds.height / 2.0f; } XIBObject* resizeMask = FindMemberAndHandle("autoresizingMask"); @@ -262,19 +271,19 @@ void UIView::InitFromStory(XIBObject* obj) { } if (getAttrib("horizontalHuggingPriority")) { - _horizontalHuggingPriority = strtof(getAttrAndHandle("horizontalHuggingPriority"), NULL); + _horizontalHuggingPriority = std::stoi(getAttrAndHandle("horizontalHuggingPriority"), NULL); } if (getAttrib("verticalHuggingPriority")) { - _verticalHuggingPriority = strtof(getAttrAndHandle("verticalHuggingPriority"), NULL); + _verticalHuggingPriority = std::stoi(getAttrAndHandle("verticalHuggingPriority"), NULL); } if (getAttrib("horizontalCompressionResistancePriority")) { - _horizontalCompressionResistancePriority = strtof(getAttrAndHandle("horizontalCompressionResistancePriority"), NULL); + _horizontalCompressionResistancePriority = std::stoi(getAttrAndHandle("horizontalCompressionResistancePriority"), NULL); } if (getAttrib("verticalCompressionResistancePriority")) { - _verticalCompressionResistancePriority = strtof(getAttrAndHandle("verticalCompressionResistancePriority"), NULL); + _verticalCompressionResistancePriority = std::stoi(getAttrAndHandle("verticalCompressionResistancePriority"), NULL); } _outputClassName = "UIView"; @@ -285,22 +294,6 @@ void UIView::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { writer->_allUIObjects->AddMember(NULL, this); } - if (_connections) { - for (int i = 0; i < _connections->count(); i++) { - XIBObject* curObj = _connections->objectAtIndex(i); - if (strcmp(curObj->_outputClassName, "UIRuntimeOutletCollectionConnection") == 0) { - UIRuntimeOutletCollectionConnection* cur = (UIRuntimeOutletCollectionConnection*)curObj; - - UIRuntimeOutletCollectionConnection* newOutlet = new UIRuntimeOutletCollectionConnection(); - newOutlet->_label = cur->_label; - newOutlet->_source = cur->_source; - newOutlet->_destination = cur->_destination; - writer->_connections->AddMember(NULL, newOutlet); - writer->AddOutputObject(newOutlet); - } - } - } - if (_subviews->count() > 0) { int count = _subviews->count(); for (int i = 0; i < count; i++) { @@ -311,9 +304,11 @@ void UIView::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { } } - AddRect(writer, "UIBounds", _bounds); - AddPoint(writer, "UICenter", _center); - if (_contentStretch.x != 0.0f || _contentStretch.y != 0.0f || _contentStretch.width != 0.0f || _contentStretch.height != 0.0f) { + if (_bounds.IsValid()) + AddRect(writer, "UIBounds", _bounds); + if (_center.IsValid()) + AddPoint(writer, "UICenter", _center); + if (_contentStretch.IsValid()) { AddRect(writer, "UIContentStretch", _contentStretch); } @@ -323,7 +318,31 @@ void UIView::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { } if (_constraints->count() > 0) { - AddOutputMember(writer, "UIViewAutolayoutConstraints", _constraints); + // remove placeholders + XIBArray *tmp = new XIBArray(); + for (int i = 0; i < _constraints->count(); i++) { + XIBObject *obj = _constraints->objectAtIndex(i); + if (obj->_outputClassName && strcmp(obj->_outputClassName, "NSLayoutConstraint") == 0) { + NSLayoutConstraint *constraint = (NSLayoutConstraint*)obj; + if (constraint->_placeholder) + continue; + } + tmp->AddMember(NULL, obj); + } + if (tmp->count()) + AddOutputMember(writer, "UIViewAutolayoutConstraints", tmp); + // FIXME: commented out as it produce a warning that XIBArrays is not final + // so tmp will leak here + // else + // delete tmp; + } + + if (_layoutGuides->count() > 0) { + if (writer->_minimumDeploymentTarget < DEPLOYMENT_TARGET_IOS11) { + writer->_wasLimitedByDeplymentTarget = true; + } else { + AddOutputMember(writer, "UIViewLayoutGuides", _layoutGuides); + } } if (_autoresizeSubviews) { @@ -379,22 +398,17 @@ void UIView::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) { obj->AddInt(writer, "UITag", _tag); } - if (_horizontalHuggingPriority >= 0.0) { - AddOutputMember(writer, "UIViewHorizontalHuggingPriority", new XIBObjectFloat(_horizontalHuggingPriority)); - } - - if (_verticalHuggingPriority >= 0.0) { - AddOutputMember(writer, "UIViewVerticalHuggingPriority", new XIBObjectFloat(_verticalHuggingPriority)); - } - - if (_horizontalCompressionResistancePriority >= 0.0) { - AddOutputMember(writer, - "UIViewHorizontalCompressionResistancePriority", - new XIBObjectFloat(_horizontalCompressionResistancePriority)); + if (_horizontalHuggingPriority != NSContentHugginPriorityDefault || _verticalHuggingPriority != NSContentHugginPriorityDefault) { + char buf[128]; + snprintf(buf, 128, "{%d, %d}", _horizontalHuggingPriority, _verticalHuggingPriority); + obj->AddString(writer, "UIViewContentHuggingPriority", strdup(buf)); } - if (_verticalCompressionResistancePriority >= 0.0) { - AddOutputMember(writer, "UIViewVerticalCompressionResistancePriority", new XIBObjectFloat(_verticalCompressionResistancePriority)); + if (_horizontalCompressionResistancePriority != NSContentCompressionResistancePriorityDefault || + _verticalCompressionResistancePriority != NSContentCompressionResistancePriorityDefault) { + char buf[128]; + snprintf(buf, 128, "{%d, %d}", _horizontalCompressionResistancePriority, _verticalCompressionResistancePriority); + obj->AddString(writer, "UIViewContentCompressionResistancePriority", strdup(buf)); } ObjectConverterSwapper::ConvertStaticMappings(writer, obj); diff --git a/tools/vsimporter/xib2nib/src/UIView.h b/tools/vsimporter/xib2nib/src/UIView.h index c2db9e2aed..097cec05c8 100644 --- a/tools/vsimporter/xib2nib/src/UIView.h +++ b/tools/vsimporter/xib2nib/src/UIView.h @@ -48,6 +48,7 @@ class UIView : public ObjectConverterSwapper { public: XIBArray* _subviews; XIBArray* _constraints; + XIBArray* _layoutGuides; UIColor* _backgroundColor; UIRect _bounds; UIRect _contentStretch; @@ -64,10 +65,10 @@ class UIView : public ObjectConverterSwapper { bool _userInteractionDisabled; bool _clearsContextBeforeDrawing; int _tag; - float _horizontalHuggingPriority; - float _verticalHuggingPriority; - float _horizontalCompressionResistancePriority; - float _verticalCompressionResistancePriority; + int _horizontalHuggingPriority; + int _verticalHuggingPriority; + int _horizontalCompressionResistancePriority; + int _verticalCompressionResistancePriority; public: UIView(); diff --git a/tools/vsimporter/xib2nib/src/UIViewController.cpp b/tools/vsimporter/xib2nib/src/UIViewController.cpp index c71d4a802c..d5cfafa6e3 100644 --- a/tools/vsimporter/xib2nib/src/UIViewController.cpp +++ b/tools/vsimporter/xib2nib/src/UIViewController.cpp @@ -21,7 +21,9 @@ #include static PropertyMapper propertyMappings[] = { - "IBUINibName", "UINibName", NULL, "IBUIResizesToFullScreen", "UIResizesToFullScreen", NULL, "IBUITitle", "UITitle", NULL, + {"IBUINibName", "UINibName", NULL}, + {"IBUIResizesToFullScreen", "UIResizesToFullScreen", NULL}, + {"IBUITitle", "UITitle", NULL}, }; static const int numPropertyMappings = sizeof(propertyMappings) / sizeof(PropertyMapper); @@ -102,7 +104,7 @@ void ScanForSegues(XIBArray* out, XIBObject* obj) { if (curMember->_obj->_className && strcmp(curMember->_obj->_className, "segue") == 0) { UIStoryboardSegue* curSegue = (UIStoryboardSegue*)curMember->_obj; - if (curSegue->_type == segueModal || curSegue->_type == seguePush) { + if (curSegue->_type != segueUnsupported) { curSegue->_parent = out; out->AddMember(NULL, curMember->_obj); } @@ -117,6 +119,8 @@ void UIViewController::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) XIBArray* segueTemplates = new XIBArray(); + if (_storyboardIdentifier) + AddString(writer, "UIStoryboardIdentifier", _storyboardIdentifier); if (_tabBarItem) AddOutputMember(writer, "UITabBarItem", _tabBarItem); if (_navigationItem) @@ -148,9 +152,7 @@ void UIViewController::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) viewWriter->ExportObject(_view); XIBObject* ownerProxy = viewWriter->AddProxy("IBFilesOwner"); - viewWriter->_topObjects->AddMember(NULL, ownerProxy); XIBObject* firstResponderProxy = viewWriter->AddProxy("IBFirstResponder"); - viewWriter->_topObjects->AddMember(NULL, firstResponderProxy); // Add view connection viewWriter->AddOutletConnection(ownerProxy, _view, "view"); @@ -171,18 +173,14 @@ void UIViewController::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) XIBObject* storyboard = writer->AddProxy("UIStoryboardPlaceholder"); writer->AddOutletConnection(this, storyboard, "storyboard"); - for (int i = 0; i < segueTemplates->count(); i++) { - UIStoryboardSegue* curSegue = (UIStoryboardSegue*)segueTemplates->objectAtIndex(i); - - writer->AddOutletConnection(curSegue, this, "viewController"); - } if (segueTemplates->count() > 0) { AddOutputMember(writer, "UIStoryboardSegueTemplates", segueTemplates); for (int i = 0; i < segueTemplates->count(); i++) { UIStoryboardSegue* curSegue = (UIStoryboardSegue*)segueTemplates->objectAtIndex(i); - NIBWriter::ExportController(curSegue->getAttrib("destination")); + writer->AddOutletConnection(curSegue, this, "viewController"); + writer->_allUIObjects->AddMember(NULL, curSegue); } } } @@ -194,4 +192,4 @@ void UIViewController::ConvertStaticMappings(NIBWriter* writer, XIBObject* obj) } ObjectConverterSwapper::ConvertStaticMappings(writer, obj); -} \ No newline at end of file +} diff --git a/tools/vsimporter/xib2nib/src/XIBObject.cpp b/tools/vsimporter/xib2nib/src/XIBObject.cpp index 1f116ae6b8..1932554f9f 100644 --- a/tools/vsimporter/xib2nib/src/XIBObject.cpp +++ b/tools/vsimporter/xib2nib/src/XIBObject.cpp @@ -446,7 +446,7 @@ CGSize XIBObject::GetSize(char* pPropName, float defaultWidth, float defaultHeig if (pObj) { const char* pStr = pObj->stringValue(); - sscanf(pStr, "{%f, %f}", &ret.width, &ret.height); + sscanf(pStr, "{%lf, %lf}", &ret.width, &ret.height); } return ret; @@ -486,6 +486,35 @@ bool XIBObject::GetBool(char* pPropName, bool defaultValue) { return defaultValue; } + +void XIBObject::PopulateInsetsFromStoryboard(const char* insetType, UIEdgeInsets& insets) { + XIBObject* insetNode = FindMemberAndHandle(const_cast(insetType)); + if (insetNode) { + insets.top = strtof(insetNode->getAttrAndHandle("minY"), NULL); + insets.left = strtof(insetNode->getAttrAndHandle("minX"), NULL); + insets.bottom = strtof(insetNode->getAttrAndHandle("maxY"), NULL); + insets.right = strtof(insetNode->getAttrAndHandle("maxX"), NULL); + } +} + +void XIBObject::PopulateRectFromStoryboard(const char* rectType, UIRect& rect) { + XIBObject* rectNode = FindMemberAndHandle(const_cast(rectType)); + if (rectNode) { + rect.x = strtof(rectNode->getAttrAndHandle("x"), NULL); + rect.y = strtof(rectNode->getAttrAndHandle("y"), NULL); + rect.width = strtof(rectNode->getAttrAndHandle("width"), NULL); + rect.height = strtof(rectNode->getAttrAndHandle("height"), NULL); + } +} + +void XIBObject::PopulateSizeFromStoryboard(const char* sizeType, CGSize& size) { + XIBObject* sizeNode = FindMemberAndHandle(const_cast(sizeType)); + if (sizeNode) { + size.width = strtof(sizeNode->getAttrAndHandle("width"), NULL); + size.height = strtof(sizeNode->getAttrAndHandle("height"), NULL); + } +} + void XIBObject::AddSize(NIBWriter* writer, char* pPropName, CGSize size) { AddData(writer, pPropName, size); } @@ -659,3 +688,7 @@ void XIBObject::getDocumentCoverage(pugi::xml_document& doc) { doc.traverse(walker); } + +XIBObject *XIBObject::createDataWriter(char *dataOut, int size) { + return new XIBObjectDataWriter(dataOut, size); +} diff --git a/tools/vsimporter/xib2nib/src/XIBObject.h b/tools/vsimporter/xib2nib/src/XIBObject.h index 3796e5e94c..750c64a0c6 100644 --- a/tools/vsimporter/xib2nib/src/XIBObject.h +++ b/tools/vsimporter/xib2nib/src/XIBObject.h @@ -21,6 +21,7 @@ #include #include #include +#include class XIBObject; @@ -46,14 +47,64 @@ class XIBArray; #include "NIBWriter.h" -typedef struct { float width, height; } CGSize; +typedef struct CGSize{ + double width, height; + + CGSize() : width(INFINITY), height(INFINITY) { + } + + CGSize(double width, double height) : width(width), height(height) { + } + + bool IsValid() { + return width != INFINITY && height != INFINITY; + } +} CGSize; + +typedef struct UIRect { + double x, y; + double width, height; + + UIRect() : x(INFINITY), y(INFINITY), width(INFINITY), height(INFINITY) { + } + + UIRect(double x, double y, double width, double height) : x(x), y(y), width(width), height(height) { + } -typedef struct { - float x, y; - float width, height; + bool IsValid() { + return x != INFINITY && y != INFINITY && width != INFINITY && height != INFINITY; + } } UIRect; -typedef struct { float x, y; } UIPoint; +typedef struct UIPoint{ + double x, y; + + UIPoint() : x(INFINITY), y(INFINITY) { + } + + UIPoint(double x, double y) : x(x), y(y) { + } + + bool IsValid() { + return x != INFINITY && y != INFINITY; + } +} UIPoint; + +typedef struct { long long location, length; } NSRange; + +typedef struct UIEdgeInsets { + double top; + double left; + double bottom; + double right; + + UIEdgeInsets() : top(INFINITY), left(INFINITY), bottom(INFINITY), right(INFINITY) { + } + + bool IsValid() { + return top != INFINITY && left != INFINITY && bottom != INFINITY && right != INFINITY; + } +} UIEdgeInsets; const char* getNodeAttrib(pugi::xml_node node, const char* name); @@ -123,13 +174,17 @@ class XIBObject { const char* GetString(char* pPropName, char* defaultValue); int GetInt(char* pPropName, int defaultValue); bool GetBool(char* pPropName, bool defaultValue); + + void PopulateInsetsFromStoryboard(const char* insetType, UIEdgeInsets& insets); + void PopulateRectFromStoryboard(const char* rectType, UIRect& rect); + void PopulateSizeFromStoryboard(const char* sizeType, CGSize& size); template void AddData(NIBWriter* writer, char* pPropName, const TData& data) { char* dataOut = (char*)malloc(sizeof(TData) + 1); - dataOut[0] = 6; + dataOut[0] = 7; // NIBOBJ_DOUBLE TODO: works only with DOUBLE entries memcpy(&dataOut[1], &data, sizeof(TData)); - AddOutputMember(writer, strdup(pPropName), new XIBObjectDataWriter(dataOut, sizeof(TData) + 1)); + AddOutputMember(writer, strdup(pPropName), createDataWriter(dataOut, sizeof(TData) + 1)); } void AddSize(NIBWriter* writer, char* pPropName, CGSize size); @@ -151,5 +206,7 @@ class XIBObject { const char* getAttrAndHandle(const char* name); XIBObject* FindMemberAndHandle(char* keyName); +private: + XIBObject* createDataWriter(char *dataOut, int size); }; #endif diff --git a/tools/vsimporter/xib2nib/src/XIBObjectInt.cpp b/tools/vsimporter/xib2nib/src/XIBObjectInt.cpp index e803bb0f10..2184bb056a 100644 --- a/tools/vsimporter/xib2nib/src/XIBObjectInt.cpp +++ b/tools/vsimporter/xib2nib/src/XIBObjectInt.cpp @@ -15,8 +15,9 @@ //****************************************************************************** #include "XIBObjectInt.h" +#include -XIBObjectInt::XIBObjectInt(int val) { +XIBObjectInt::XIBObjectInt(long long val) { _val = val; } @@ -24,32 +25,27 @@ int XIBObjectInt::intValue() { return _val; } +long long XIBObjectInt::longValue() { + return _val; +} + bool XIBObjectInt::NeedsSerialization() { return false; } void XIBObjectInt::WriteData(NIBWriter* writer) { - unsigned int fullVal = (unsigned int)_val; - - if (fullVal <= 0xFF) { + if (_val >= SCHAR_MIN && _val <= SCHAR_MAX) { writer->WriteByte(NIBOBJ_INT8); - writer->WriteBytes(&fullVal, 1); - } else if (fullVal <= 0xFFFF) { + writer->WriteBytes(&_val, 1); + } else if (_val >= SHRT_MIN && _val <= SHRT_MAX) { writer->WriteByte(NIBOBJ_INT16); - writer->WriteBytes(&fullVal, 2); - } else { + writer->WriteBytes(&_val, 2); + } else if (_val >= INT_MIN && _val <= INT_MAX) { writer->WriteByte(NIBOBJ_INT32); - writer->WriteBytes(&fullVal, 4); + writer->WriteBytes(&_val, 4); + } else { + writer->WriteByte(NIBOBJ_INT64); + writer->WriteBytes(&_val, 8); } } -XIBObjectNumber::XIBObjectNumber(int num) { - _val = num; - _className = "NSNumber"; -} - -void XIBObjectNumber::EmitObject(NIBWriter* writer) { - _outputClassName = "NSNumber"; - - AddOutputMember(writer, "NS.intval", new XIBObjectInt(_val)); -} diff --git a/tools/vsimporter/xib2nib/src/XIBObjectInt.h b/tools/vsimporter/xib2nib/src/XIBObjectInt.h index 7f0ac99956..6dcc620932 100644 --- a/tools/vsimporter/xib2nib/src/XIBObjectInt.h +++ b/tools/vsimporter/xib2nib/src/XIBObjectInt.h @@ -21,11 +21,12 @@ class XIBObjectInt : public XIBObject { private: - int _val; + long long _val; public: - XIBObjectInt(int val); + XIBObjectInt(long long val); int intValue(); + long long longValue(); virtual bool NeedsSerialization(); void WriteData(NIBWriter* writer); }; @@ -40,12 +41,5 @@ class XIBObjectDataWriter : public XIBObject { void WriteData(NIBWriter* writer); }; -class XIBObjectNumber : public XIBObject { - int _val; - -public: - XIBObjectNumber(int val); - void EmitObject(NIBWriter* writer); -}; #endif \ No newline at end of file diff --git a/tools/vsimporter/xib2nib/src/XIBObjectNumber.cpp b/tools/vsimporter/xib2nib/src/XIBObjectNumber.cpp new file mode 100644 index 0000000000..dfe561c4b5 --- /dev/null +++ b/tools/vsimporter/xib2nib/src/XIBObjectNumber.cpp @@ -0,0 +1,51 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#include "XIBObjectNumber.h" +#include "XIBObjectInt.h" +#include "XIBObjectDouble.h" + +XIBObjectNumber::XIBObjectNumber(int num) { + _className = "NSNumber"; + _keyName = "NS.intval"; + _val = new XIBObjectInt(num); +} + +XIBObjectNumber::XIBObjectNumber(long long num) { + _className = "NSNumber"; + _keyName = "NS.intval"; + _val = new XIBObjectInt(num); +} + +XIBObjectNumber::XIBObjectNumber(bool val) { + _className = "NSNumber"; + _keyName = "NS.intval"; + _val = new XIBObjectInt(val ? 1 : 0); +} + +XIBObjectNumber::XIBObjectNumber(double val) { + _className = "NSNumber"; + _keyName = "NS.dblval"; + _val = new XIBObjectDouble(val); +} + +void XIBObjectNumber::EmitObject(NIBWriter* writer) { + _outputClassName = "NSNumber"; + + AddOutputMember(writer, _keyName, _val); +} + + diff --git a/tools/vsimporter/xib2nib/src/XIBObjectNumber.h b/tools/vsimporter/xib2nib/src/XIBObjectNumber.h new file mode 100644 index 0000000000..30ce425da8 --- /dev/null +++ b/tools/vsimporter/xib2nib/src/XIBObjectNumber.h @@ -0,0 +1,31 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + + +#pragma once +#include "XIBObject.h" + +class XIBObjectNumber : public XIBObject { + XIBObject *_val; + const char *_keyName; +public: + explicit XIBObjectNumber(long long val); + explicit XIBObjectNumber(int val); + explicit XIBObjectNumber(bool val); + explicit XIBObjectNumber(double val); + void EmitObject(NIBWriter* writer); +}; + diff --git a/tools/vsimporter/xib2nib/src/XIBObjectTypes.cpp b/tools/vsimporter/xib2nib/src/XIBObjectTypes.cpp index 2d7f771f73..6f2d7dc784 100644 --- a/tools/vsimporter/xib2nib/src/XIBObjectTypes.cpp +++ b/tools/vsimporter/xib2nib/src/XIBObjectTypes.cpp @@ -43,7 +43,7 @@ XIBObjectString::XIBObjectString(const char* str) { } void XIBObjectString::InitFromStory(XIBObject* obj) { - _strVal = _strdup(obj->_node.text().as_string()); + _strVal = strdup(obj->_node.text().as_string()); } const char* XIBObjectString::stringValue() { @@ -190,17 +190,22 @@ int XIBObjectBool::intValue() { } XIBObjectReal::XIBObjectReal(pugi::xml_node node) { + _val = strtod(node.child_value(), NULL); _node = node; } +XIBObjectReal::XIBObjectReal(double val) { + _val = val; +}; + + bool XIBObjectReal::NeedsSerialization() { return false; } void XIBObjectReal::WriteData(NIBWriter* writer) { writer->WriteByte(NIBOBJ_DOUBLE); - double dVal = 0.0f; - writer->WriteBytes(&dVal, 8); + writer->WriteBytes(&_val, 8); } XIBArray::XIBArray(pugi::xml_node node) { diff --git a/tools/vsimporter/xib2nib/src/XIBObjectTypes.h b/tools/vsimporter/xib2nib/src/XIBObjectTypes.h index 29e5326d6f..b56b272c8f 100644 --- a/tools/vsimporter/xib2nib/src/XIBObjectTypes.h +++ b/tools/vsimporter/xib2nib/src/XIBObjectTypes.h @@ -21,6 +21,7 @@ #include "XIBObjectFloat.h" #include "XIBObjectDouble.h" #include "XIBObjectInt.h" +#include "XIBObjectNumber.h" #include "XIBDictionary.h" #include "XIBObjectNil.h" @@ -60,8 +61,11 @@ class XIBObjectBool : public XIBObject { }; class XIBObjectReal : public XIBObject { +private: + double _val; public: XIBObjectReal(pugi::xml_node node); + XIBObjectReal(double val); virtual bool NeedsSerialization(); void WriteData(NIBWriter* writer); }; diff --git a/tools/vsimporter/xib2nib/src/XIBObjectValue.h b/tools/vsimporter/xib2nib/src/XIBObjectValue.h new file mode 100644 index 0000000000..a9b58502de --- /dev/null +++ b/tools/vsimporter/xib2nib/src/XIBObjectValue.h @@ -0,0 +1,91 @@ +//****************************************************************************** +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + + +#pragma once +#include "XIBObject.h" +#include +#include +#include + +#define NSPointNSValueType 1 +#define NSSizeNSValueType 2 +#define NSRectNSValueType 3 +#define NSRangeNSValueType 4 + +template +class XIBObjectValue : public XIBObject { + TData _data; +public: + explicit XIBObjectValue(TData &v ) : _data(v) { + _outputClassName = "NSValue"; + } + + void EmitObject(NIBWriter* writer) { + EmitObject(writer, _data); + } + +private: + + const char *to_str(const UIPoint &point) { + std::stringstream ss; + ss << "{" << point.x << ", " < #include +#include #include -#include +//#include #include #include -#include +//#include +#include #include "XIBObject.h" #include "XIBObjectTypes.h" #include "XIBDocument.h" #include "NIBWriter.h" +#include "UIViewController.h" #include "Plist.hpp" #include "miscutils.h" #include "versionutils.h" -#include "..\WBITelemetry\WBITelemetry.h" +#include "../WBITelemetry/WBITelemetry.h" // These globals should only be employed when dealing with storyboard files (.storyboard) // They are only set once when we determine that the input format is a storyboard @@ -49,9 +52,133 @@ std::string GetOutputFilename(const char* filename) { return ret; } -extern std::map _g_exportedControllers; +// convert string presentation of version to hex enctoded integer "a.b.c" > 0xaaaabbcc +static int stringToVersion(const char *str){ + int v = -1; + std::stringstream ss(str); + std::string s; + std::vector items; + while (getline(ss, s, '.')) { + items.push_back(std::stoi(s)); + } + + // small sanity for range checking + if (items.size() && items[0] >= 0 && items[0] <= 0xFFFF) { + v = items[0] << 16; + if (items.size() > 1) + v = (items[1] >= 0 && items[1] <= 0xFF) ? (v | items[1] << 8) : -1; + if (v >= 0 && items.size() > 2) + v = (items[2] >= 0 && items[2] <= 0xFF) ? (v | items[2] << 8) : -1; + } + + return v; +} + + + + +static NIBWriter* WriteStoryNibToFile(const char *szFilename, XIBArray* arr, const int minDeploymentVersion) { + FILE* fpOut = fopen(GetOutputFilename(szFilename).c_str(), "wb"); + NIBWriter* writer = new NIBWriter(fpOut, NULL, NULL); + writer->_minimumDeploymentTarget = minDeploymentVersion; + + XIBObject* ownerProxy = writer->FindProxy("IBFilesOwner"); + if (!ownerProxy) + ownerProxy = writer->AddProxy("IBFilesOwner"); + + for (int i = 0; i < arr->count(); i++) { + XIBObject* curObj = arr->objectAtIndex(i); + + writer->ExportObject(curObj); + if (curObj->getAttrib("sceneMemberID")) { + if (strcmp(curObj->getAttrib("sceneMemberID"), "viewController") == 0) { + writer->AddOutletConnection(ownerProxy, curObj, "sceneViewController"); + } + } + } + + writer->WriteObjects(); + fclose(fpOut); + + return writer; +} + +void ExportStoryBoardController(std::map exportedControllers, const char* controllerId, + const int minDeploymentVersion) { + char szFilename[255]; + + XIBObject* controller = XIBObject::findReference(controllerId); + UIViewController* uiViewController = dynamic_cast(controller); + if (!uiViewController) { + // object isn't really a controller + printf("Object %s is not a controller\n", controller->stringValue()); + return; + } + + const char* controllerIdentifier = uiViewController->_storyboardIdentifier; + if (controllerIdentifier == NULL) { + // not all viewcontrollers will have a storyboard identifier. If they don't use the controller Id for the key. + controllerIdentifier = controllerId; + } + + // Check if we've already written out the controller + if (exportedControllers.find(controllerIdentifier) != exportedControllers.end()) { + return; + } + + sprintf(szFilename, "%s.nib", controllerIdentifier); + exportedControllers[controllerIdentifier] = controllerIdentifier; + + XIBArray* viewObjects = (XIBArray*)controller->_parent; + + const char *outFile = GetOutputFilename(szFilename).c_str(); + printf("Writing %s\n", outFile); + + if (minDeploymentVersion < 0) { + // version is not limited compile to recent one + NIBWriter* writer = WriteStoryNibToFile(outFile, (XIBArray*)viewObjects, DEPLOYMENT_TARGET_RECENT); + assert(!writer->_wasLimitedByDeplymentTarget); + } else { + // there is limitation applied + // compile to test file to check if there will be limitation during the run + std::string tmp = std::string(outFile) + ".tmp"; + NIBWriter* writer = WriteStoryNibToFile(tmp.c_str(), (XIBArray*)viewObjects, minDeploymentVersion); + if (writer->_wasLimitedByDeplymentTarget) { + // limitation has applied, so begin plan b: + // create dir with outFile name + struct stat st = { 0 }; + stat(outFile, &st); + if (!(((st.st_mode) & S_IFMT) == S_IFDIR) && _mkdir(outFile) != 0) { + printf("Unable to create directory %s err=%d\n", outFile, errno); + exit(-1); + return; + } + + // move tmp file to + std::string dest = std::string(outFile) + "/runtime.nib"; + if (rename(tmp.c_str(), dest.c_str()) != 0) { + printf("Failed to move nib to %s/runtime.nib err=%d\n", outFile, errno); + exit(-1); + return; + } + + // and now generate unlimited version + dest = std::string(outFile) + "/objects-11.0+.nib"; + NIBWriter* writer = WriteStoryNibToFile(dest.c_str(), (XIBArray*)viewObjects, DEPLOYMENT_TARGET_RECENT); + assert(!writer->_wasLimitedByDeplymentTarget); + } else { + // no limitations, just rename file to target + if (rename(tmp.c_str(), outFile) != 0) { + printf("Failed to rename nib to %s err=%d\n", outFile, errno); + exit(-1); + return; + } + } + } +} -void ConvertStoryboard(pugi::xml_document& doc) { + +void ConvertStoryboard(pugi::xml_document& doc, const int minDeploymentVersion) { pugi::xml_node curNode = doc.first_child(); // Storyboard XIB file - get topmost controller, then export it @@ -69,14 +196,17 @@ void ConvertStoryboard(pugi::xml_document& doc) { // Print which XML nodes we did not handle during the parse for diagnostic purpose. XIBObject::getDocumentCoverage(doc); - NIBWriter::ExportAllControllers(); + std::map exportedControllers; + for (const char* cur : UIViewController::_viewControllerNames) { + ExportStoryBoardController(exportedControllers, cur, minDeploymentVersion); + } Plist::dictionary_type viewControllerInfo; viewControllerInfo[std::string("UIStoryboardDesignatedEntryPointIdentifier")] = std::string(initialController); viewControllerInfo[std::string("UIStoryboardVersion")] = (int)1; Plist::dictionary_type viewControllerMappings; - for (auto curController : _g_exportedControllers) { + for (auto curController : exportedControllers) { viewControllerMappings[curController.first] = curController.second; } viewControllerInfo[std::string("UIViewControllerIdentifiersToNibNames")] = viewControllerMappings; @@ -85,7 +215,29 @@ void ConvertStoryboard(pugi::xml_document& doc) { Plist::writePlistBinary(GetOutputFilename("Info.plist").c_str(), viewControllerInfo); } -void ConvertXIB3ToNib(FILE* fpOut, pugi::xml_document& doc) { +NIBWriter* WriteNibToFile(const char *outFile, XIBArray* arr, const int minDeploymentVersion) { + FILE* fpOut = fopen(outFile, "wb"); + if (!fpOut) { + printf("Error opening %s\n", outFile); + exit(-1); + return NULL; + } + + NIBWriter* writer = new NIBWriter(fpOut, NULL, NULL); + writer->_minimumDeploymentTarget = minDeploymentVersion; + for (int i = 0; i < arr->count(); i++) { + XIBObject* curObj = arr->objectAtIndex(i); + + writer->ExportObject(curObj); + } + + writer->WriteObjects(); + fclose(fpOut); + + return writer; +} + +void ConvertXIB3ToNib(const char *outFile, pugi::xml_document& doc, const int minDeploymentVersion) { pugi::xml_node curNode = doc.first_child(); // XIB3 file @@ -95,19 +247,50 @@ void ConvertXIB3ToNib(FILE* fpOut, pugi::xml_document& doc) { XIBArray* viewObjects = rootDocument->Objects(); if (viewObjects) { - NIBWriter* writer = new NIBWriter(fpOut, NULL, NULL); - - XIBArray* arr = (XIBArray*)viewObjects; - for (int i = 0; i < arr->count(); i++) { - XIBObject* curObj = arr->objectAtIndex(i); + if (minDeploymentVersion < 0) { + // version is not limited compile to recent one + NIBWriter* writer = WriteNibToFile(outFile, (XIBArray*)viewObjects, DEPLOYMENT_TARGET_RECENT); + assert(!writer->_wasLimitedByDeplymentTarget); + } else { + // there is limitation applied + // compile to test file to check if there will be limitation during the run + std::string tmp = std::string(outFile) + ".tmp"; + NIBWriter* writer = WriteNibToFile(tmp.c_str(), (XIBArray*)viewObjects, minDeploymentVersion); + if (writer->_wasLimitedByDeplymentTarget) { + // limitation has applied, so begin plan b: + // create dir with outFile name + struct stat st = { 0 }; + stat(outFile, &st); + if (!(((st.st_mode) & S_IFMT) == S_IFDIR) && _mkdir(outFile) != 0) { + printf("Unable to create directory %s err=%d\n", outFile, errno); + exit(-1); + return; + } + + // move tmp file to + std::string dest = std::string(outFile) + "/runtime.nib"; + if (rename(tmp.c_str(), dest.c_str()) != 0) { + printf("Failed to move nib to %s/runtime.nib err=%d\n", outFile, errno); + exit(-1); + return; + } - writer->ExportObject(curObj); + // and now generate unlimited version + dest = std::string(outFile) + "/objects-11.0+.nib"; + NIBWriter* writer = WriteNibToFile(dest.c_str(), (XIBArray*)viewObjects, DEPLOYMENT_TARGET_RECENT); + assert(!writer->_wasLimitedByDeplymentTarget); + } else { + // no limitations, just rename file to target + if (rename(tmp.c_str(), outFile) != 0) { + printf("Failed to rename nib to %s err=%d\n", outFile, errno); + exit(-1); + return; + } + } } - - writer->WriteObjects(); } } -void ConvertXIBToNib(FILE* fpOut, pugi::xml_document& doc) { +void ConvertXIBToNib(const char *outFile, pugi::xml_document& doc) { pugi::xml_node dataNode = doc.first_element_by_path("/archive/data"); XIBObject* root = new XIBObject(); @@ -138,7 +321,6 @@ void ConvertXIBToNib(FILE* fpOut, pugi::xml_document& doc) { // Attempt to find any associated custom class name char szPropName[255]; sprintf(szPropName, "%d.CustomClassName", objId); - const char* pClassName = obj->ClassName(); XIBObject* customName = properties->ObjectForKey(szPropName); if (customName) { @@ -231,11 +413,28 @@ void ConvertXIBToNib(FILE* fpOut, pugi::xml_document& doc) { nibRoot->AddMember("UINibAccessibilityConfigurationsKey", accessibilityObjects); nibRoot->AddMember("UINibKeyValuePairsKey", new XIBArray()); + FILE* fpOut = fopen(outFile, "wb"); + if (!fpOut) { + printf("Error opening %s\n", outFile); + exit(-1); + return; + } + NIBWriter* writer = new NIBWriter(fpOut); writer->_allUIObjects = allObjects; writer->_visibleWindows = visibleWindows; writer->AddOutputObject(nibRoot); writer->WriteData(); + + fclose(fpOut); +} + +void printUsageAndExit(int code) { + printf("Usage:\n"); + printf("xib2nib [--minimum-deployment-target version] --compile \n"); + + TELEMETRY_FLUSH(); + exit(code); } int main(int argc, char* argv[]) { @@ -248,19 +447,66 @@ int main(int argc, char* argv[]) { } TELEMETRY_SET_INTERNAL(isMSFTInternalMachine()); - string machineID = getMachineID(); + std::string machineID = getMachineID(); if (!machineID.empty()) { TELEMETRY_SET_MACHINEID(machineID.c_str()); } TELEMETRY_EVENT_DATA(L"Xib2NibStart", getProductVersion().c_str()); + + // parsing arguments + const char *inFile = NULL; + const char *outFile = NULL; + int minVersion = -1; + + int idx = 1; + while (idx < argc) { + if (*argv[idx] == '-') { + // parse argument + if (strcmp("--compile", argv[idx]) == 0) { + if (idx + 1 < argc) { + outFile = argv[idx + 1]; + idx += 2; + } else { + printf("Error missing argument after --compile\n"); + printUsageAndExit(-1); + return -1; + } + } else if (strcmp("--minimum-deployment-target", argv[idx]) == 0) { + if (idx + 1 < argc) { + minVersion = stringToVersion(argv[idx + 1]); + if (minVersion < 0) { + printf("Error invalid version argument %s\n", argv[idx + 1]); + printUsageAndExit(-1); + return -1; + } + idx += 2; + } else { + printf("Error missing argument after --compile\n"); + printUsageAndExit(-1); + return -1; + } + } else { + printf("Error unknown parameter %s\n", argv[idx]); + printUsageAndExit(-1); + return -1; + } + } else { + inFile = argv[idx]; + idx += 1; + } + } + + if (!inFile || !outFile) { + printf("Error missing required parameters"); + printUsageAndExit(-1); + return -1; + } pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(argv[1]); + pugi::xml_parse_result result = doc.load_file(inFile); if (!result) { - printf("Error opening %s\n", argv[1]); - TELEMETRY_FLUSH(); - exit(2); + printf("Error opening %s\n", inFile); return -1; } @@ -268,54 +514,28 @@ int main(int argc, char* argv[]) { const char* type = getNodeAttrib(rootNode, "type"); if (!type) { printf("Unable to find input type\n"); - TELEMETRY_FLUSH(); - exit(3); return -1; } if (strcmp(rootNode.name(), "document") == 0 && strcmp(type, "com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB") == 0) { - if (argc < 3) { - printf("Usage: xib2nib input.storyboard \n"); - TELEMETRY_FLUSH(); - exit(1); - return -1; - } - struct stat st = { 0 }; - stat(argv[2], &st); - if (!(((st.st_mode) & S_IFMT) == S_IFDIR) && _mkdir(argv[2]) != 0) { - printf("Unable to create directory %s err=%d\n", argv[2], errno); + stat(outFile, &st); + if (!(((st.st_mode) & S_IFMT) == S_IFDIR) && _mkdir(outFile) != 0) { + printf("Unable to create directory %s err=%d\n", outFile, errno); return -1; } g_isStoryboard = true; - strcpy_s(g_outputDirectory, arraySize(g_outputDirectory), argv[2]); - ConvertStoryboard(doc); + strcpy_s(g_outputDirectory, arraySize(g_outputDirectory), outFile); + ConvertStoryboard(doc, minVersion); } else if (strstr(type, ".XIB") != NULL) { - if (argc < 3) { - printf("Usage: xib2nib input.xib output.nib\n"); - TELEMETRY_FLUSH(); - exit(1); - return -1; - } - - FILE* fpOut = fopen(argv[2], "wb"); - if (!fpOut) { - printf("Error opening %s\n", argv[2]); - TELEMETRY_FLUSH(); - exit(3); - return -1; - } - if (strcmp(rootNode.name(), "document") == 0) { - ConvertXIB3ToNib(fpOut, doc); + ConvertXIB3ToNib(outFile, doc, minVersion); } else { - ConvertXIBToNib(fpOut, doc); + ConvertXIBToNib(outFile, doc); } - fclose(fpOut); } else { printf("Unable to determine input type type=\"%s\"\n", type); TELEMETRY_FLUSH(); - exit(4); return -1; }