/XibParser.as

http://github.com/daoki2/xib2js · ActionScript · 1011 lines · 811 code · 39 blank · 161 comment · 187 complexity · 77ef255ba415f63fb4f5830910bb0f05 MD5 · raw file

  1. /**
  2. * XIB parser for Titanium Mobile
  3. * @author Copyright (c) 2010-2012 daoki2
  4. * @version 2.0.0
  5. *
  6. * Copyright (c) 2010-2012 daoki2
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. package {
  27. import flash.display.*;
  28. import flash.errors.IllegalOperationError;
  29. import flash.filesystem.*;
  30. import flash.utils.*;
  31. import mx.controls.*;
  32. import mx.utils.*;
  33. /**
  34. * This is a utility class to parse the .xib file for Titanium Mobile
  35. */
  36. public class XibParser {
  37. private static const _TYPE:Array = [
  38. "com.apple.InterfaceBuilder3.CocoaTouch.XIB",
  39. "com.apple.InterfaceBuilder3.CocoaTouch.XIB",
  40. "com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB",
  41. "com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB"
  42. ];
  43. private static const _VERSION:Array = [
  44. "7.10",
  45. "8.00",
  46. "7.10",
  47. "8.00"
  48. ];
  49. private static var _xib:XML;
  50. private static var _rootObjects:Array = [];
  51. private static var _objRecords:Array = [];
  52. /**
  53. * XibParser class can not create instance
  54. */
  55. public function XibParser() {
  56. throw new IllegalOperationError("XibParser class can not create instance");
  57. }
  58. /**
  59. * parse the .xib file
  60. */
  61. public static function exec(_file:File, _checkVersion:Boolean = true):void {
  62. // read .xib file
  63. var _fs:FileStream = new FileStream();
  64. _fs.open(_file, FileMode.READ);
  65. _xib = new XML(_fs.readUTFBytes(_fs.bytesAvailable));
  66. _fs.close();
  67. if (_checkVersion) {
  68. if (!checkVersion()) {
  69. Alert.show("This version of .xib file is not supported: " + _xib.@version.toString(), "ERROR");
  70. trace("Version error");
  71. return;
  72. }
  73. }
  74. // parse the IBObjectContainer first because it is easy to get the name of the object
  75. var children:XMLList;
  76. var child:XML;
  77. children = _xib.children();
  78. for each (child in children) {
  79. switch (child.name().toString()) {
  80. case "data":
  81. parseIBObjectContainerData(child);
  82. break;
  83. default:
  84. trace("Unknown XML list:", child.name());
  85. break;
  86. }
  87. }
  88. children = _xib.children();
  89. for each (child in children) {
  90. switch (child.name().toString()) {
  91. case "data":
  92. parseRootObjectsData(child);
  93. break;
  94. default:
  95. trace("Unknown XML list:", child.name());
  96. break;
  97. }
  98. }
  99. }
  100. /**
  101. * cleanup the parser
  102. */
  103. public static function cleanup():void {
  104. _rootObjects = new Array();
  105. _objRecords = new Array();
  106. _xib = null;
  107. }
  108. /**
  109. * Return the parsed data
  110. */
  111. public static function getParsedData():Array {
  112. return _rootObjects;
  113. }
  114. /**
  115. * parse IBObjectContainer of <data>
  116. */
  117. private static function parseIBObjectContainerData(xml:XML):void {
  118. var children:XMLList = xml.children();
  119. for each (var child:XML in children) {
  120. switch (child.name().toString()) {
  121. case "object":
  122. if (child.attribute("class").toString() == "IBObjectContainer" && child.@key.toString() == "IBDocument.Objects") {
  123. parseObjectContainer(child);
  124. break;
  125. }
  126. break;
  127. default:
  128. // Do nothing
  129. break;
  130. }
  131. }
  132. }
  133. /**
  134. * parse RootObjects of <data>
  135. */
  136. private static function parseRootObjectsData(xml:XML):void {
  137. var children:XMLList = xml.children();
  138. for each (var child:XML in children) {
  139. switch (child.name().toString()) {
  140. case "array":
  141. case "object":
  142. if (child.attribute("class").toString() == "NSMutableArray" && child.@key.toString() == "IBDocument.RootObjects") {
  143. parseRootObject(child);
  144. break;
  145. }
  146. break;
  147. default:
  148. // Do nothing
  149. break;
  150. }
  151. }
  152. }
  153. /**
  154. * parse RootObjects
  155. */
  156. private static function parseRootObject(xml:XML):void {
  157. var children:XMLList = xml.children();
  158. for each (var child:XML in children) {
  159. switch (child.name().toString()) {
  160. case "object":
  161. var _result:Object = null;
  162. switch (child.attribute("class").toString()) {
  163. case "IBUIWindow":
  164. _result = parseUIWindow(child);
  165. break;
  166. case "IBUITabBarController":
  167. _result = parseUITabBarController(child);
  168. break;
  169. case "IBUINavigationController":
  170. _result = parseUINavigationController(child);
  171. break;
  172. case "IBUIViewController":
  173. _result = parseUIViewController(child);
  174. break;
  175. case "IBUITableViewController":
  176. _result = parseUITableViewController(child);
  177. break;
  178. case "IBUISplitViewController":
  179. _result = parseUISplitViewController(child);
  180. break;
  181. case "IBUIImagePickerController":
  182. _result = parseUIImagePickerController(child);
  183. break;
  184. case "IBUITableViewCell":
  185. _result = parseUITableViewCell(child);
  186. break;
  187. case "IBUIView":
  188. _result = parseUIView(child);
  189. break;
  190. default:
  191. // Do nothing
  192. trace("# skipped:1", child.attribute("class").toString());
  193. break;
  194. }
  195. if (_result != null) {
  196. _rootObjects.push(_result);
  197. }
  198. break;
  199. default:
  200. // Do nothing
  201. trace("# skipped:2", child.name().toString());
  202. break;
  203. }
  204. }
  205. }
  206. /**
  207. * parse UIWindow
  208. */
  209. private static function parseUIWindow(xml:XML):Object {
  210. trace("parse UIWindow", getObjectName(xml.@id.toString()), xml.@id);
  211. return {obj:"IBUIWindow", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), subviews:getSubviews(xml), propertires:getProperties(xml)};
  212. }
  213. /**
  214. * parse UITabBarController
  215. */
  216. private static function parseUITabBarController(xml:XML):Object {
  217. trace("parse IBUITabBarController", getObjectName(xml.@id.toString()), xml.@id);
  218. var _viewControllers:Array = [];
  219. var children:XMLList = xml.children();
  220. for each (var child:XML in children) {
  221. switch (child.name().toString()) {
  222. case "object":
  223. if (child.@key.toString() == "IBUISelectedViewController") {
  224. _viewControllers.push(parseViewController(child));
  225. }
  226. if (child.@key.toString() == "IBUIViewControllers") {
  227. var _result:Array = parseViewControllers(child);
  228. if (_result.length > 0)
  229. _viewControllers = _viewControllers.concat(_result);
  230. }
  231. break;
  232. default:
  233. // Do nothing
  234. trace("# skipped:3", child.name().toString());
  235. break;
  236. }
  237. }
  238. return {obj:"IBUITabBarController", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), views:_viewControllers};
  239. }
  240. /**
  241. * parse ViewControllers
  242. */
  243. private static function parseViewControllers(xml:XML):Array {
  244. trace("parseViewControllers");
  245. var _views:Array = [];
  246. var children:XMLList = xml.children();
  247. for each (var child:XML in children) {
  248. var _result:Object = parseViewController(child);
  249. if (_result != null)
  250. _views.push(_result);
  251. }
  252. return (_views.length > 0 ? _views : null);
  253. }
  254. /**
  255. * parse ViewController
  256. */
  257. private static function parseViewController(xml:XML):Object {
  258. switch (xml.name().toString()) {
  259. case "object":
  260. if (xml.attribute("class").toString() == "IBUIViewController") {
  261. return parseUIViewController(xml);
  262. }
  263. if (xml.attribute("class").toString() == "IBUINavigationController") {
  264. return parseUINavigationController(xml);
  265. }
  266. if (xml.attribute("class").toString() == "IBUITableViewController") {
  267. return parseUITableViewController(xml);
  268. }
  269. if (xml.attribute("class").toString() == "IBUIImagePickerController") {
  270. return parseUIImagePickerController(xml);
  271. }
  272. break;
  273. default:
  274. // do nothing
  275. trace("# skipped:4", xml.name().toString());
  276. break;
  277. }
  278. return null;
  279. }
  280. /**
  281. * parse UIViewController
  282. */
  283. private static function parseUIViewController(xml:XML):Object {
  284. trace("parse UIViewController", getObjectName(xml.@id.toString()), xml.@id);
  285. var _tabItem:Object = null;
  286. var _navItem:Object = null;
  287. var _view:Object = null;
  288. var children:XMLList = xml.children();
  289. for each (var child:XML in children) {
  290. switch(child.name().toString()) {
  291. case "object":
  292. switch(child.attribute("class").toString()) {
  293. case "IBUINavigationItem":
  294. trace("UINavigationItem");
  295. _navItem = {title:getUITitle(child)};
  296. break;
  297. case "IBUITabBarItem":
  298. trace("UITabBarItem");
  299. _tabItem = {title:getUITitle(child)};
  300. break;
  301. case "IBUIView":
  302. _view = parseUIView(child);
  303. break;
  304. case "IBUIScrollView":
  305. _view = parseUIScrollView(child);
  306. break;
  307. case "IBUITextView":
  308. _view = parseUITextView(child);
  309. break;
  310. case "IBUIImageView":
  311. _view = parseUIImageView(child);
  312. break;
  313. case "IBUITableView":
  314. _view = parseUITableView(child);
  315. break;
  316. case "IBUIWebView":
  317. _view = parseUIWebView(child);
  318. break;
  319. case "IBMKMapView":
  320. _view = parseMKMapView(child);
  321. break;
  322. default:
  323. //_view = parseControlls(child);
  324. break;
  325. }
  326. break;
  327. default:
  328. // do nothing
  329. trace("# skipped:5", child.name().toString());
  330. break;
  331. }
  332. }
  333. return {obj:"IBUIViewController", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), view:_view, navItem:_navItem, tabItem:_tabItem};
  334. }
  335. /**
  336. * parse UINavigationController
  337. */
  338. private static function parseUINavigationController(xml:XML):Object {
  339. trace("parse UINavigationController", getObjectName(xml.@id.toString()), xml.@id);
  340. var _views:Array = [];
  341. var children:XMLList = xml.children();
  342. var _tabItem:Object = null;
  343. for each (var child:XML in children) {
  344. switch(child.name().toString()) {
  345. case "array":
  346. case "object":
  347. //if (child.attribute("class").toString() == "NSMutableArray" && child.@key.toString() == "IBUIViewControllers") {
  348. if (child.@key.toString() == "IBUIViewControllers") {
  349. _views = parseViewControllers(child);
  350. }
  351. if (child.attribute("class").toString() == "IBUITabBarItem") {
  352. trace("UITabBarItem");
  353. _tabItem = {title:getUITitle(child)};
  354. }
  355. break;
  356. default:
  357. // do nothing
  358. trace("# skipped:6", child.name().toString());
  359. break;
  360. }
  361. }
  362. return {obj:"IBUINavigationController", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), views:_views, tabItem:_tabItem};
  363. }
  364. /**
  365. * parse UITableViewController
  366. */
  367. private static function parseUITableViewController(xml:XML):Object {
  368. trace("parse UITableViewController", getObjectName(xml.@id.toString()), xml.@id);
  369. var _tabItem:Object = null;
  370. var _navItem:Object = null;
  371. var children:XMLList = xml.children();
  372. for each (var child:XML in children) {
  373. switch(child.name().toString()) {
  374. case "object":
  375. switch(child.attribute("class").toString()) {
  376. case "IBUINavigationItem":
  377. trace("UINavigationItem");
  378. _navItem = {title:getUITitle(child)};
  379. break;
  380. case "IBUITabBarItem":
  381. trace("UITabBarItem");
  382. _tabItem = {title:getUITitle(child)};
  383. break;
  384. case "IBUITableView":
  385. trace("UITableView");
  386. break;
  387. default:
  388. // do nothing
  389. break;
  390. }
  391. default:
  392. // do nothing
  393. break;
  394. }
  395. }
  396. return {obj:"IBUITableViewController", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), navItem:_navItem, tabItem:_tabItem}
  397. }
  398. /**
  399. * parse UIImagePickerController
  400. */
  401. private static function parseUIImagePickerController(xml:XML):Object {
  402. trace("parse UIImagePickerController", getObjectName(xml.@id.toString()), xml.@id);
  403. var _navBar:Object = null;
  404. var _views:Array;
  405. var children:XMLList = xml.children();
  406. for each (var child:XML in children) {
  407. switch(child.name().toString()) {
  408. case "array":
  409. case "object":
  410. if (child.attribute("class").toString() == "IBUINavigationBar") {
  411. // do nothing
  412. }
  413. if (child.attribute("class").toString() == "NSMutableArray" && child.@key.toString() == "IBUIViewControllers") {
  414. _views = parseViewControllers(child);
  415. }
  416. break;
  417. default:
  418. // do nothing
  419. trace("# skipped:7", child.name().toString());
  420. break;
  421. }
  422. }
  423. return {obj:"IBUIImagePickerController", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), views:_views, navBar:_navBar};
  424. }
  425. /**
  426. * parse UISplitViewController
  427. */
  428. private static function parseUISplitViewController(xml:XML):Object {
  429. trace("parse IBUISplitViewController", getObjectName(xml.@id.toString()), xml.@id);
  430. var _viewControllers:Array = [];
  431. var children:XMLList = xml.children();
  432. for each (var child:XML in children) {
  433. switch (child.name().toString()) {
  434. case "object":
  435. if (child.@key.toString() == "IBUIMasterViewController") {
  436. _viewControllers.push(parseUINavigationController(child));
  437. }
  438. if (child.@key.toString() == "IBUIDetailViewController") {
  439. if (child.attribute("class").toString() == "IBUIViewController")
  440. _viewControllers.push(parseUIViewController(child));
  441. if (child.attribute("class").toString() == "IBUINavigationController")
  442. _viewControllers.push(parseUINavigationController(child));
  443. }
  444. break;
  445. default:
  446. // Do nothing
  447. trace("# skipped:8", child.name().toString());
  448. break;
  449. }
  450. }
  451. return {obj:"IBUISplitViewController", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), views:_viewControllers};
  452. }
  453. /**
  454. * parse UITableViewCell
  455. */
  456. private static function parseUITableViewCell(xml:XML):Object {
  457. trace("parse UITableViewCell", getObjectName(xml.@id.toString()), xml.@id);
  458. var _subviews:Array = [];
  459. var children:XMLList = xml.children();
  460. for each (var child:XML in children) {
  461. switch(child.name().toString()) {
  462. case "array":
  463. case "object":
  464. if (child.attribute("class").toString() == "NSMutableArray" && child.@key.toString() == "NSSubviews") {
  465. trace("NSSubviews");
  466. _subviews = getSubviews(child);
  467. }
  468. break;
  469. default:
  470. // do nothing
  471. trace("# skipped:9", child.name().toString());
  472. break;
  473. }
  474. }
  475. return {obj:"IBUITableViewCell", name:getObjectName(xml.@id.toString()), id:xml.@id.toString, subviews:_subviews, properties:getProperties(xml)};
  476. }
  477. /**
  478. * parse UIView
  479. */
  480. private static function parseUIView(xml:XML, scrollable:Boolean = false):Object {
  481. trace("parse", (scrollable ? "IBUIScrollView" : "IBUIView"), xml.@id);
  482. var _subviews:Array = [];
  483. var children:XMLList = xml.children();
  484. for each (var child:XML in children) {
  485. switch(child.name().toString()) {
  486. case "array":
  487. case "object":
  488. if (child.attribute("class").toString() == "NSMutableArray" && child.@key.toString() == "NSSubviews") {
  489. trace("NSSubviews");
  490. _subviews = getSubviews(child);
  491. }
  492. break;
  493. default:
  494. // do nothing
  495. trace("# skipped:10", child.name().toString());
  496. break;
  497. }
  498. }
  499. return {obj:(scrollable ? "IBUIScrollView" : "IBUIView"), name:getObjectName(xml.@id.toString()), id:xml.@id.toString, subviews:_subviews, properties:getProperties(xml)};
  500. }
  501. /**
  502. * parse UIScrollView
  503. */
  504. private static function parseUIScrollView(xml:XML):Object {
  505. return parseUIView(xml, true);
  506. }
  507. /**
  508. * parse UITextView
  509. */
  510. private static function parseUITextView(xml:XML):Object {
  511. trace("parse IBUITextView", getObjectName(xml.@id.toString()), xml.@id.toString());
  512. return {obj:"IBUITextView", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), properties:getProperties(xml)};
  513. }
  514. /**
  515. * parse UIImageView
  516. */
  517. private static function parseUIImageView(xml:XML):Object {
  518. trace("parse IBUIImageView", getObjectName(xml.@id.toString()), xml.@id.toString());
  519. return {obj:"IBUIImageView", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), properties:getProperties(xml)};
  520. }
  521. /**
  522. * parse UITableView
  523. */
  524. private static function parseUITableView(xml:XML):Object {
  525. trace("parse IBUITableView", getObjectName(xml.@id.toString()), xml.@id.toString());
  526. return {obj:"IBUITableView", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), properties:getProperties(xml)};
  527. }
  528. /**
  529. * parse UIWebView
  530. */
  531. private static function parseUIWebView(xml:XML):Object {
  532. trace("parse IBUIWebView", getObjectName(xml.@id.toString()), xml.@id.toString());
  533. return {obj:"IBUIWebView", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), properties:getProperties(xml)};
  534. }
  535. /**
  536. * parse UIMKMapView
  537. */
  538. private static function parseMKMapView(xml:XML):Object {
  539. trace("parse IBMKMapView", getObjectName(xml.@id.toString()), xml.@id.toString());
  540. return {obj:"IBMKMapView", name:getObjectName(xml.@id.toString()), id:xml.@id.toString(), properties:getProperties(xml)};
  541. }
  542. /**
  543. * parse Subviews
  544. */
  545. private static function getSubviews(xml:XML):Array {
  546. var result:Array = [];
  547. var children:XMLList = xml.children();
  548. for each (var child:XML in children) {
  549. switch (child.name().toString()) {
  550. case "array":
  551. case "object":
  552. switch(child.attribute("class").toString()) {
  553. case "NSMutableArray":
  554. if (child.@key.toString() == "NSSubviews") {
  555. result.push({obj:"NSSubviews", subviews:getSubviews(child)});
  556. }
  557. break;
  558. case "IBUIActivityIndicatorView":
  559. case "IBUIButton":
  560. case "IBUIDatePicker":
  561. case "IBUIImageView":
  562. case "IBUILabel":
  563. case "IBUIPickerView":
  564. case "IBUIProgressView":
  565. case "IBUISearchBar":
  566. case "IBUISegmentedControl":
  567. case "IBUISlider":
  568. case "IBUISwitch":
  569. case "IBUITextField":
  570. case "IBUITextView":
  571. case "IBUIToolbar":
  572. trace("parse", child.attribute("class"), child.@id);
  573. result.push({obj:child.attribute("class").toString(), name:getObjectName(child.@id.toString()), id:child.@id.toString(), properties:getProperties(child)});
  574. break;
  575. case "IBUIView":
  576. result.push(parseUIView(child));
  577. break;
  578. case "IBUIScrollView":
  579. result.push(parseUIScrollView(child));
  580. break;
  581. case "IBUITextView":
  582. result.push(parseUITextView(child));
  583. break;
  584. case "IBUIImageView":
  585. result.push(parseUIImageView(child));
  586. break;
  587. case "IBUITableView":
  588. result.push(parseUITableView(child));
  589. break;
  590. case "IBUIWebView":
  591. result.push(parseUIWebView(child));
  592. break;
  593. case "IBMKMapView":
  594. result.push(parseMKMapView(child));
  595. break;
  596. default:
  597. // Do nothing;
  598. trace("# skipped:11", child.attribute("class").toString());
  599. break;
  600. }
  601. break;
  602. default:
  603. // Do nothing
  604. trace("# skipped:12", child.name().toString());
  605. break;
  606. }
  607. }
  608. return result;
  609. }
  610. /**
  611. * parse property
  612. */
  613. private static function getProperties(xml:XML):Array {
  614. var result:Array = [];
  615. var children:XMLList = xml.children();
  616. var _children:XMLList;
  617. var _child:XML;
  618. for each (var child:XML in children) {
  619. switch (child.name().toString()) {
  620. case "string":
  621. if (child.@key.toString() == "NSFrame") {
  622. trace("parse NSFrame", child.toString());
  623. result.push({type:"frame", value:child.toString()});
  624. break;
  625. }
  626. if (child.@key.toString() == "NSFrameSize") {
  627. trace("parse NSFrameSize", child.toString());
  628. result.push({type:"framesize", value:child.toString()});
  629. break;
  630. }
  631. if (child.@key.toString() == "IBUIText") {
  632. trace("parse IBUIText", child.toString());
  633. if (xml.attribute("class").toString() == "IBUITextField" || xml.attribute("class").toString() == "IBUITextView") {
  634. result.push({type:"value", value:"'" + child.toString() + "'"});
  635. } else {
  636. result.push({type:"text", value:child.toString()});
  637. }
  638. break;
  639. }
  640. if (child.@key.toString() == "IBUINormalTitle") {
  641. trace("parse IBUINormalTitle", child.toString());
  642. result.push({type:"title", value:child.toString()});
  643. break;
  644. }
  645. break;
  646. case "bool":
  647. if (child.@key.toString() == "IBUIOn") {
  648. trace("parse IBUIOn", child.toString());
  649. result.push({type:"value", value:(child.toString() == "YES" ? "true" : "false")});
  650. }
  651. break;
  652. case "float":
  653. if (child.@key.toString() == "IBUIValue" || child.@key.toString() == "IBUIProgress") {
  654. trace("parse IBUIValue", child.toString());
  655. result.push({type:"value", value:child.toString()});
  656. break;
  657. }
  658. if (child.@key.toString() == "IBUIMinValue") {
  659. trace("parse IBUIMinValue", child.toString());
  660. result.push({type:"min", value:child.toString()});
  661. break;
  662. }
  663. if (child.@key.toString() == "IBUIMaxValue") {
  664. trace("parse IBUIMaxValue", child.toString());
  665. result.push({type:"max", value:child.toString()});
  666. break;
  667. }
  668. break;
  669. case "object":
  670. // parse Font
  671. if (child.@key.toString() == "IBUIFont") {
  672. trace("parse IBUIFont", child.toString());
  673. _children = child.children();
  674. var _fontName:String = "";
  675. var _fontSize:String = "";
  676. for each (_child in _children) {
  677. switch(_child.name().toString()) {
  678. case "string":
  679. if (_child.@key.toString() == "NSName") {
  680. _fontName = _child.toString();
  681. }
  682. break;
  683. case "double":
  684. if (_child.@key.toString() == "NSSize") {
  685. _fontSize = _child.toString();
  686. }
  687. break;
  688. default:
  689. trace("# skipped:13", _child.name().toString());
  690. break;
  691. }
  692. }
  693. result.push({type:"font", value:_fontName + "," + _fontSize});
  694. break;
  695. }
  696. // parse Segement
  697. if (child.@key.toString() == "IBSegmentTitles") {
  698. trace("parse IBSegmentTitles", child.toString());
  699. _children = child.children();
  700. var _labels:String = "";
  701. for each (_child in _children) {
  702. if (_child.name().toString() == "string") {
  703. _labels += "'" + _child.toString() + "', ";
  704. }
  705. }
  706. result.push({type:"labels", value:"[" + _labels.substring(0, _labels.length - 2) + "]"});
  707. break;
  708. }
  709. // parse Toolbar
  710. if (child.@key.toString() == "IBUIItems") {
  711. _children = child.children();
  712. var _toolbar:String = "";
  713. for each (_child in _children) {
  714. if (_child.attribute("class").toString() == "IBUIBarButtonItem") {
  715. trace("parse IBUIBarButtonItem", _child.toString());
  716. var __children:XMLList = _child.children();
  717. var _title:String = "";
  718. var _id:String = "";
  719. var _width:String = "";
  720. for each(var __child:XML in __children) {
  721. switch (__child.name().toString()) {
  722. case "string":
  723. if (__child.@key.toString() == "IBUITitle") {
  724. _title = __child.toString();
  725. }
  726. break;
  727. case "int":
  728. if (__child.@key.toString() == "IBUISystemItemIdentifier") {
  729. _id = __child.toString();
  730. }
  731. break;
  732. case "float":
  733. if (__child.@key.toString() == "IBUIWidth") {
  734. _width = __child.toString();
  735. }
  736. break;
  737. default:
  738. trace("# skipped:14", __child.name().toString());
  739. break;
  740. }
  741. }
  742. _toolbar += "{title: " + _title + ", id: " + _id + ", width: " + _width + "}, ";
  743. }
  744. }
  745. result.push({type:"toolbar", value:"[" + _toolbar.substring(0, _toolbar.length - 2) + "]"});
  746. break;
  747. }
  748. // parse NSColor
  749. if (child.attribute("class").toString() == "NSColor") {
  750. _children = child.children();
  751. var _colorSpace:int = -1;
  752. var _bytes:Array = [];
  753. var _color:String = "";
  754. for each (_child in _children) {
  755. switch (_child.name().toString()) {
  756. case "int":
  757. if (_child.@key.toString() == "NSColorSpace") {
  758. _colorSpace = _child.toString();
  759. }
  760. break;
  761. case "bytes":
  762. _color = convertToColor(_child.toString(), _colorSpace, _child.@key.toString());
  763. break;
  764. default:
  765. // do nothing
  766. break;
  767. }
  768. }
  769. if (_color != "") {
  770. var _colorType:String = "color";
  771. switch(child.@key.toString()) {
  772. case "IBUIBackgroundColor":
  773. result.push({type:"backgroundColor", value:_color});
  774. break;
  775. case "IBUINormalTitleColor":
  776. case "IBUITextColor":
  777. result.push({type:"color", value:_color});
  778. break;
  779. default:
  780. trace("# skipped:15", child.@key.toString());
  781. break;
  782. }
  783. }
  784. break;
  785. }
  786. break;
  787. default:
  788. // Do nothing
  789. trace("# skipped:16", child.name().toString());
  790. break;
  791. }
  792. }
  793. return result;
  794. }
  795. /**
  796. * parse ObjectContainer
  797. */
  798. private static function parseObjectContainer(xml:XML):void {
  799. trace("parse ObjectContainer");
  800. var children:XMLList = xml.children();
  801. for each (var child:XML in children) {
  802. switch (child.name().toString()) {
  803. case "object":
  804. if (child.attribute("class").toString() == "IBMutableOrderedSet" && child.@key.toString() == "objectRecords") {
  805. parseObjectRecords(child);
  806. break;
  807. }
  808. break;
  809. default:
  810. // Do nothing
  811. trace("# skipped:17", child.name().toString());
  812. break;
  813. }
  814. }
  815. }
  816. /**
  817. * parse ObjectRecords
  818. */
  819. private static function parseObjectRecords(xml:XML):void {
  820. trace("parse ObjectRecords");
  821. var children:XMLList = xml.children();
  822. for each (var child:XML in children) {
  823. switch (child.name().toString()) {
  824. case "array":
  825. case "object":
  826. //if (child.attribute("class").toString() == "NSArray" && child.@key.toString() == "orderedObjects") {
  827. if (child.@key.toString() == "orderedObjects") {
  828. parseOrderedObject(child);
  829. break;
  830. }
  831. break;
  832. default:
  833. // do nothing
  834. break;
  835. }
  836. }
  837. }
  838. /**
  839. * parse OrderedObjects
  840. */
  841. private static function parseOrderedObject(xml:XML):void {
  842. var children:XMLList = xml.children();
  843. for each (var child:XML in children) {
  844. switch (child.name().toString()) {
  845. case "object":
  846. if (child.attribute("class").toString() == "IBObjectRecord") {
  847. if (child.string.toString() != "") {
  848. for (var i:uint = 0; i < child.reference.length(); i++) {
  849. if (child.reference[i].@key.toString() == "object") {
  850. trace("add id:", child.reference[i].@ref.toString(), "name:", child.string.toString());
  851. _objRecords.push({id:child.reference[i].@ref.toString(), name:child.string.toString()});
  852. }
  853. }
  854. break;
  855. }
  856. }
  857. break;
  858. default:
  859. // do nothing
  860. trace("# skipped:18", child.name().toString());
  861. break;
  862. }
  863. }
  864. }
  865. /**
  866. * convert base64 encoded value to color value
  867. */
  868. private static function convertToColor(_code:String, type:int, key:String):String {
  869. //trace("convertToColor", _code, type, key);
  870. var result:String = "";
  871. // The _code is not just Base64 encoded data
  872. // It seems the padding character is "AA" not "=". Why?
  873. if (_code.length <=3) {
  874. if (_code == "MAA") {
  875. return "#000000";
  876. } else {
  877. _code = _code.substring(0, _code.length -1) + "==";
  878. }
  879. } else {
  880. var _padding:String = _code.substring(_code.length - 2, _code.length);
  881. if (_padding == "AA") {
  882. _code = _code.substring(0, _code.length - 2);
  883. }
  884. }
  885. var _padNum:int = _code.length % 4;
  886. if (_padNum != 0) {
  887. while(_padNum != 4) {
  888. _code += "=";
  889. _padNum++;
  890. }
  891. }
  892. var decoder:Base64Decoder = new Base64Decoder();
  893. decoder.decode(_code);
  894. var _bytes:ByteArray = decoder.toByteArray();
  895. var i:int;
  896. var _r:String;
  897. var _g:String;
  898. var _b:String;
  899. var _color:Array;
  900. switch(key) {
  901. case "NSRGB":
  902. _color = _bytes.readUTFBytes(_bytes.length).split(" ");
  903. _r = uint(parseFloat(_color[0])*255).toString(16);
  904. _g = uint(parseFloat(_color[1])*255).toString(16);
  905. _b = uint(parseFloat(_color[2])*255).toString(16);
  906. result = "#" + (_r.length < 2 ? "0" + _r : _r) + (_g.length < 2 ? "0" + _g : _g) + (_b.length < 2 ? "0" + _b : _b);
  907. if (_color.length == 4)
  908. result += ":" + parseFloat(_color[3]);
  909. break;
  910. case "NSCMYK":
  911. _color = _bytes.readUTFBytes(_bytes.length).split(" ");
  912. var _c:float = parseFloat(_color[0]);
  913. var _m:float = parseFloat(_color[1]);
  914. var _y:float = parseFloat(_color[2]);
  915. var _k:float = parseFloat(_color[3]);
  916. _r = uint((1 - Math.min(1, _c * (1 - _k) + _k)) * 255).toString(16);
  917. _g = uint((1 - Math.min(1, _m * (1 - _k) + _k)) * 255).toString(16);
  918. _b = uint((1 - Math.min(1, _y * (1 - _k) + _k)) * 255).toString(16);
  919. result = "#" + (_r.length < 2 ? "0" + _r : _r) + (_g.length < 2 ? "0" + _g : _g) + (_b.length < 2 ? "0" + _b : _b);
  920. if (_color.length == 5)
  921. result += ":" + parseFloat(_color[4]);
  922. break;
  923. case "NSWhite": // Grayscale
  924. _color = _bytes.readUTFBytes(_bytes.length).split(" ");
  925. _r = uint(parseFloat(_color[0])*255).toString(16);
  926. result = "#" + (_r.length < 2 ? "0" + _r : _r) + (_r.length < 2 ? "0" + _r : _r) + (_r.length < 2 ? "0" + _r : _r);
  927. if (_color.length == 2)
  928. result += ":" + parseFloat(_color[1]);
  929. break;
  930. default:
  931. trace("# skipped:19", key, type);
  932. break;
  933. }
  934. return result;
  935. }
  936. /**
  937. * get IBUITitle
  938. */
  939. private static function getUITitle(xml:XML):String {
  940. var children:XMLList = xml.children();
  941. for each (var child:XML in children) {
  942. if (child.@key.toString() == "IBUITitle")
  943. return child.toString();
  944. }
  945. return "";
  946. }
  947. /**
  948. * get the name of the object
  949. */
  950. private static function getObjectName(id:String):String {
  951. for each (var val:* in _objRecords) {
  952. if (val.id == id) {
  953. return val.name;
  954. }
  955. }
  956. return "";
  957. }
  958. /**
  959. * Check version
  960. */
  961. private static function checkVersion():Boolean {
  962. if (_xib.name().toString() == "archive") {
  963. trace(_xib.@type, _xib.@version);
  964. for (var i:uint = 0; i < _TYPE.length; i++) {
  965. if (_xib.@type.toString() == _TYPE[i] && _xib.@version.toString() == _VERSION[i])
  966. return true;
  967. }
  968. }
  969. return false;
  970. }
  971. }
  972. }