not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

916 lines
27 KiB

  1. // Local cache of icon coordonate
  2. var networkItemsCache = [];
  3. var wifiItemsCache = [];
  4. var lastWifiUpdate = 0;
  5. // Neighborhood view
  6. enyo.kind({
  7. name: "Sugar.NeighborhoodView",
  8. kind: enyo.Control,
  9. components: [
  10. {name: "owner", kind: "Sugar.Icon", size: constant.sizeNeighbor, colorized: true, classes: "owner-icon", showing: false},
  11. {name: "server", kind: "Sugar.Icon", size: constant.sizeNeighbor, colorized: true, classes: "server-icon", showing: false},
  12. {name: "network", showing: true, onresize: "draw", components: []},
  13. {name: "otherview", showing: true, components: []},
  14. {name: "networkPopup", kind: "Sugar.Popup", showing: false},
  15. {name: "empty", classes: "cloud-empty", showing: false},
  16. {name: "message", classes: "cloud-message", showing: false},
  17. {name: "settings", classes: "cloud-line", showing: false, components:[
  18. {name: "gotosettings", kind: "Sugar.IconButton", icon: {directory: "icons", icon: "preferences-system.svg"}, classes: "listview-button cloud-gotosettings", ontap: "doSettings"}
  19. ]},
  20. {name: "refresh", classes: "cloud-line", showing: false, components:[
  21. {name: "refreshstate", kind: "Sugar.IconButton", icon: {directory: "icons", icon: "system-restart.svg"}, classes: "listview-button cloud-gotosettings", ontap: "doRefresh"}
  22. ]}
  23. ],
  24. // Constructor: init list
  25. create: function() {
  26. this.inherited(arguments);
  27. this.$.owner.setIcon({directory: "icons", icon: "owner-icon.svg"});
  28. this.$.owner.setPopupShow(enyo.bind(this, "showBuddyPopup"));
  29. this.$.owner.setPopupHide(enyo.bind(this, "hideBuddyPopup"));
  30. if (window.sugarizerOS) {
  31. this.$.server.setIcon({directory: "icons", icon:"cloud-one.svg"});
  32. } else {
  33. this.$.server.setIcon({directory: "icons", icon: "network-wireless-connected-100.svg"});
  34. }
  35. this.$.server.setPopupShow(enyo.bind(this, "showServerPopup"));
  36. this.$.server.setPopupHide(enyo.bind(this, "hideServerPopup"));
  37. var cacheData = this.findInCache({icon: this.$.server});
  38. var serverColor = Math.floor(Math.random()*xoPalette.colors.length);
  39. this.$.server.setColorizedColor(cacheData ? cacheData.colorvalue : xoPalette.colors[serverColor]);
  40. this.users = [];
  41. this.activities = [];
  42. this.eeMode = false;
  43. this.timer = window.setInterval(enyo.bind(this, "updateNetworkState"), constant.timerUpdateNetwork);
  44. if (presence.isConnected() || window.sugarizerOS) {
  45. this.updateNetworkState();
  46. }
  47. if (l10n.language.direction == "rtl") {
  48. this.$.message.addClass("rtl-10");
  49. }
  50. this.draw();
  51. },
  52. // Get linked toolbar
  53. getToolbar: function() {
  54. if (this.toolbar == null)
  55. this.toolbar = new Sugar.NeighborhoodToolbar();
  56. return this.toolbar;
  57. },
  58. // Get linked popup
  59. getPopup: function() {
  60. return this.$.networkPopup;
  61. },
  62. createWifiIcons: function (items) {
  63. // If SugarizerOS, adding Wireless networks icons
  64. if (window.sugarizerOS) {
  65. var networkIcons = [];
  66. var networks = sugarizerOS.networks;
  67. var wifiInTutorial = false;
  68. for (var i = 0; i < networks.length; i++) {
  69. var currentNetwork = networks[i];
  70. var encryptionString = sugarizerOS.getEncryptionString(currentNetwork.capabilities);
  71. var connectedString = "";
  72. var securedString = "";
  73. var pwr = (-1 * currentNetwork.RSSI) % 10;
  74. if (currentNetwork.isConnected) {
  75. connectedString = "-connected";
  76. } else if (encryptionString != "OPEN") {
  77. securedString = "-locked";
  78. }
  79. if (pwr > 0) {
  80. if (pwr % 2 != 0) {
  81. pwr += 1;
  82. }
  83. pwr = pwr * 10;
  84. cacheIcon = sugarizerOS.getNetworkIconFromCache(currentNetwork.BSSID);
  85. if (!cacheIcon) {
  86. currentNetwork.networkId = currentNetwork.BSSID;
  87. currentNetwork.shared = false;
  88. currentNetwork.shared.id = currentNetwork.BSSID;
  89. currentNetwork.color = xoPalette.colors[Math.floor(Math.random() * xoPalette.colors.length)];
  90. } else {
  91. currentNetwork = cacheIcon;
  92. }
  93. iconString = "network-wireless"+connectedString+securedString+"-0"+pwr+".svg";
  94. if (pwr == 100) {
  95. iconString = "network-wireless"+connectedString+securedString+"-"+pwr+".svg";
  96. }
  97. var icon = this.$.network.createComponent({
  98. kind: "Sugar.Icon",
  99. icon: {directory: "icons", icon: iconString},
  100. size: constant.sizeNeighbor,
  101. colorized: true,
  102. colorizedColor: currentNetwork.color,
  103. popupShow: enyo.bind(this, "showWifiPopup"),
  104. popupHide: enyo.bind(this, "hideWifiPopup"),
  105. data: currentNetwork
  106. },
  107. {owner: this}
  108. );
  109. icon.render();
  110. if (!wifiInTutorial) {
  111. tutorial.setElement("wifi", icon.getAttribute("id"));
  112. wifiInTutorial = true;
  113. }
  114. networkIcons.push(icon);
  115. sugarizerOS.addNetworkIconToCache(currentNetwork);
  116. var item = {icon: icon, size: icon.getSize(), locked: false, child: []};
  117. items.push(item);
  118. }}
  119. }
  120. },
  121. // Update
  122. updateNetworkState: function() {
  123. var currentcolor = preferences.getColor();
  124. if (presence.isConnected() && currentcolor.stroke == "#005FE4" && currentcolor.fill == "#FF2B34" && this.toolbar && this.toolbar.getSearchText() == "Sugarizer contributors") {
  125. if (!this.eeMode) {
  126. var list = new Sugar.EE({mode: 3}).contributors();
  127. for (var i = 0 ; i < list.length ; i++) {
  128. this.users.push(list[i]);
  129. }
  130. this.eeMode = true;
  131. this.draw();
  132. this.filterNetwork();
  133. }
  134. } else if (presence.isConnected()) {
  135. this.$.owner.setShowing(true);
  136. this.$.server.setShowing(true);
  137. this.$.empty.setShowing(false);
  138. this.$.message.setShowing(false);
  139. this.$.settings.setShowing(false);
  140. this.$.refresh.setShowing(false);
  141. if (app.toolbar && app.toolbar.showServerWarning) {
  142. app.toolbar.showServerWarning(false);
  143. }
  144. presence.listUsers(enyo.bind(this, "userListReceived"));
  145. presence.listSharedActivities(enyo.bind(this, "sharedListReceived"));
  146. this.eeMode = false;
  147. }
  148. else if (window.sugarizerOS) {
  149. now = new Date().getTime();
  150. this.$.owner.setShowing(true);
  151. if (presence.isConnected())
  152. this.$.server.setShowing(true);
  153. this.$.empty.setShowing(false);
  154. this.$.message.setShowing(false);
  155. this.$.settings.setShowing(false);
  156. this.$.refresh.setShowing(false);
  157. sugarizerOS.isWifiEnabled(function(value){
  158. if (value != 0) {
  159. sugarizerOS.scanWifi();
  160. } else {
  161. sugarizerOS.networks = [];
  162. }
  163. });
  164. if (wifiItemsCache != sugarizerOS.networks && (now - lastWifiUpdate) > constant.wifiUpdateTime) {
  165. this.draw();
  166. wifiItemsCache = sugarizerOS.networks;
  167. lastWifiUpdate = now;
  168. }
  169. presence.listUsers(enyo.bind(this, "userListReceived"));
  170. presence.listSharedActivities(enyo.bind(this, "sharedListReceived"));
  171. this.eeMode = false;
  172. }
  173. else {
  174. this.$.owner.setShowing(false);
  175. this.$.server.setShowing(false);
  176. this.$.empty.setShowing(true);
  177. this.$.message.setShowing(true);
  178. if (app.toolbar && app.toolbar.showServerWarning) {
  179. app.toolbar.showServerWarning(true);
  180. }
  181. if (preferences.isConnected()) {
  182. this.$.message.setContent(l10n.get("UnableToConnect"));
  183. this.$.refresh.setShowing(true);
  184. } else {
  185. this.$.message.setContent(l10n.get("ServerNotSet"));
  186. this.$.settings.setShowing(true);
  187. }
  188. this.eeMode = false;
  189. }
  190. },
  191. // Popup menu for buddy handling
  192. showBuddyPopup: function(icon) {
  193. // Create popup
  194. this.getPopup().setHeader({
  195. icon: icon.icon,
  196. colorized: true,
  197. colorizedColor: null,
  198. name: preferences.getName(),
  199. title: null,
  200. action: null
  201. });
  202. this.getPopup().setItems(null);
  203. var items = [];
  204. items.push({
  205. icon: {directory: "icons", icon: "system-shutdown.svg"},
  206. colorized: false,
  207. name: l10n.get("Logoff"),
  208. action: enyo.bind(this, "doLogoff"),
  209. data: null
  210. });
  211. items.push({
  212. icon: {directory: "icons", icon: "system-restart.svg"},
  213. colorized: false,
  214. name: l10n.get("Restart"),
  215. action: enyo.bind(this, "doRestart"),
  216. data: null
  217. });
  218. items.push({
  219. icon: {directory: "icons", icon: "preferences-system.svg"},
  220. colorized: false,
  221. name: l10n.get("MySettings"),
  222. action: enyo.bind(this, "doSettings"),
  223. data: null
  224. });
  225. this.getPopup().setFooter(items);
  226. // Show popup
  227. this.getPopup().showPopup();
  228. },
  229. hideBuddyPopup: function(icon) {
  230. if (!this || !this.getPopup || !icon || !this.getPopup() || this.getPopup().cursorIsInside() || icon.cursorIsInside()) {
  231. return false;
  232. }
  233. this.getPopup().hidePopup();
  234. return true;
  235. },
  236. doLogoff: function() {
  237. stats.trace(constant.viewNames[app.getView()], 'click', 'logoff');
  238. this.getPopup().hidePopup();
  239. if (!preferences.isConnected() || (preferences.isConnected() && !preferences.getOptions("sync"))) {
  240. this.otherview = this.$.otherview.createComponent({kind: "Sugar.DialogWarningMessage"}, {owner:this});
  241. this.otherview.show();
  242. } else {
  243. preferences.addUserInHistory();
  244. util.cleanDatastore(null, function() {
  245. util.restartApp();
  246. });
  247. }
  248. },
  249. doRestart: function() {
  250. stats.trace(constant.viewNames[app.getView()], 'click', 'restart');
  251. util.restartApp();
  252. },
  253. doSettings: function() {
  254. stats.trace(constant.viewNames[app.getView()], 'click', 'my_settings');
  255. this.getPopup().hidePopup();
  256. this.otherview = this.$.otherview.createComponent({kind: "Sugar.DialogServer"}, {owner:this});
  257. this.otherview.show();
  258. },
  259. doRefresh: function() {
  260. if (!presence.isConnected()) {
  261. var that = this;
  262. presence.joinNetwork(function(error, user) {
  263. if (error) {
  264. console.log("WARNING: Can't connect to presence server");
  265. } else {
  266. that.updateNetworkState();
  267. }
  268. });
  269. } else {
  270. this.updateNetworkState();
  271. }
  272. },
  273. // Popup menu for server handling
  274. showServerPopup: function(icon) {
  275. // Create popup
  276. var name = myserver.getServer();
  277. var info = preferences.getServer();
  278. if (info && info.name) {
  279. name = info.name;
  280. }
  281. this.getPopup().setHeader({
  282. icon: icon.icon,
  283. colorized: true,
  284. colorizedColor: icon.colorizedColor,
  285. name: name,
  286. title: l10n.get("Connected"),
  287. action: null
  288. });
  289. this.getPopup().setItems(null);
  290. this.getPopup().setFooter(null);
  291. // Show popup
  292. this.getPopup().showPopup();
  293. },
  294. hideServerPopup: function(icon) {
  295. if (!this || !this.getPopup || !icon || !this.getPopup() || this.getPopup().cursorIsInside() || icon.cursorIsInside()) {
  296. return false;
  297. }
  298. this.getPopup().hidePopup();
  299. return true;
  300. },
  301. disconnect: function() {
  302. sugarizerOS.disconnectWifi();
  303. this.getPopup().hidePopup();
  304. },
  305. forgetPassword: function(network) {
  306. sugarizerOS.forgetNetwork(network.SSID);
  307. this.getPopup().hidePopup();
  308. },
  309. joinNetwork: function(network) {
  310. var t = this;
  311. sugarizerOS.isKnownNetwork(network.SSID, function (result) {
  312. if (result == 0) {
  313. sugarizerOS.setKey(network.SSID, "", true);
  314. } else {
  315. sugarizerOS.joinNetwork(network.SSID);
  316. }
  317. t.getPopup().hidePopup();
  318. });
  319. },
  320. enterKey: function (network) {
  321. this.getPopup().hidePopup();
  322. var t = this;
  323. sugarizerOS.isKnownNetwork(network.SSID, function (result) {
  324. if (result == 0) {
  325. sugarizerOS.NetworkBuffer = network;
  326. t.otherview = t.$.otherview.createComponent({
  327. kind: "Sugar.DialogNetworkKey"
  328. });
  329. t.otherview.show();
  330. } else {
  331. sugarizerOS.joinNetwork(network.SSID)
  332. }
  333. })
  334. },
  335. //Popup menu for Wireless Network handling
  336. showWifiPopup: function(icon) {
  337. // Create popup
  338. var data = icon.getData();
  339. var iconName = data.SSID + " (" + data.RSSI + ")" + "[" + sugarizerOS.getEncryptionString(data.capabilities) + "]";
  340. var power = (-1 * data.RSSI) % 5;
  341. this.getPopup().setHeader({
  342. icon: icon.icon,
  343. colorized: true,
  344. colorizedColor: icon.colorizedColor,
  345. name: iconName,
  346. title: data.BSSID,
  347. action: null
  348. });
  349. var items = [];
  350. var t = this;
  351. sugarizerOS.getWifiSSID(function (ssid) {
  352. if (ssid == null || ssid !== data.SSID) {
  353. item = {
  354. icon: {
  355. directory: "icons", icon: "activity-start.svg"
  356. },
  357. colorized: false,
  358. name: l10n.get("JoinNetwork"),
  359. action: enyo.bind(t, "joinNetwork"),
  360. data: [icon.getData(), null]
  361. };
  362. if (sugarizerOS.getEncryptionString(data.capabilities) != "OPEN") {
  363. item.action = enyo.bind(t, "enterKey");
  364. }
  365. } else {
  366. item = {
  367. icon: {
  368. directory: "icons",
  369. icon: "activity-start.svg"
  370. },
  371. colorized: false,
  372. name: l10n.get("Disconnect"),
  373. action: enyo.bind(t, "disconnect"),
  374. data: [icon.getData(), null]
  375. };
  376. }
  377. items.push(item);
  378. sugarizerOS.isKnownNetwork(data.SSID, function (result) {
  379. if (result == 1) {
  380. item = {
  381. icon: {
  382. directory: "icons",
  383. icon: "activity-start.svg"
  384. },
  385. colorized: false,
  386. name: l10n.get("ForgetPassword"),
  387. action: enyo.bind(t, "forgetPassword"),
  388. data: [icon.getData(), null]
  389. };
  390. if (sugarizerOS.getEncryptionString(data.capabilities) != "OPEN") {
  391. items.push(item);
  392. }
  393. }
  394. t.getPopup().setItems(items);
  395. t.getPopup().setFooter(null);
  396. // Show popup
  397. t.getPopup().showPopup();
  398. })
  399. })
  400. },
  401. hideWifiPopup: function (icon) {
  402. if ((!this || !this.getPopup || !icon || !this.getPopup() || this.getPopup() && this.getPopup().cursorIsInside()) || icon.cursorIsInside()) {
  403. return false;
  404. }
  405. this.getPopup().hidePopup();
  406. return true;
  407. },
  408. // Popup menu for user handling
  409. showUserPopup: function(icon) {
  410. // Create popup
  411. this.getPopup().setHeader({
  412. icon: icon.icon,
  413. colorized: true,
  414. colorizedColor: icon.colorizedColor,
  415. name: icon.getData().name,
  416. title: null,
  417. action: null
  418. });
  419. this.getPopup().setItems(null);
  420. this.getPopup().setFooter(null);
  421. // Show popup
  422. this.getPopup().showPopup();
  423. },
  424. hideUserPopup: function(icon) {
  425. if (!this || !this.getPopup || !icon || !this.getPopup() || this.getPopup().cursorIsInside() || icon.cursorIsInside()) {
  426. return false;
  427. }
  428. this.getPopup().hidePopup();
  429. return true;
  430. },
  431. // Popup menu for shared activities handling
  432. showActivityPopup: function(icon) {
  433. // Create popup
  434. this.getPopup().setHeader({
  435. icon: icon.icon,
  436. colorized: true,
  437. colorizedColor: icon.colorizedColor,
  438. name: icon.getData().activity.name,
  439. title: null,
  440. action: null
  441. });
  442. var items = [];
  443. items.push({
  444. icon: {directory: "icons", icon: "activity-start.svg"},
  445. colorized: false,
  446. name: l10n.get("JoinActivity"),
  447. action: enyo.bind(this, "joinActivity"),
  448. data: [icon.getData(), null]
  449. });
  450. this.getPopup().setItems(items);
  451. this.getPopup().setFooter(null);
  452. // Show popup
  453. this.getPopup().showPopup();
  454. },
  455. hideActivityPopup: function(icon) {
  456. if (!this || !this.getPopup || !icon || !this.getPopup() || this.getPopup().cursorIsInside() || icon.cursorIsInside()) {
  457. return false;
  458. }
  459. this.getPopup().hidePopup();
  460. return true;
  461. },
  462. // Join a shared activity
  463. joinActivity: function(data) {
  464. preferences.runActivity(
  465. data.activity,
  466. null,
  467. data.activity.name,
  468. data.shared.id);
  469. },
  470. // User list received
  471. userListReceived: function(users) {
  472. // Ensure that an update is need
  473. if (this.users.length == users.length) {
  474. var len = this.users.length;
  475. var found = 0;
  476. for(var i = 0 ; i < len ; i++) {
  477. for(var j = 0 ; j < len ; j++) {
  478. if (users[i].networkId == this.users[j].networkId) {
  479. found++;
  480. break;
  481. }
  482. }
  483. }
  484. if (found == len) {
  485. return;
  486. }
  487. }
  488. // Retrieve users
  489. this.users = users;
  490. // Add dummy users for testing
  491. var dummy = 0;
  492. for (var i = 0 ; i < dummy ; i++) {
  493. this.users.push({networkId: "nxx"+i, name: "dummy "+i, colorvalue: xoPalette.colors[Math.floor(Math.random()*xoPalette.colors.length)]});
  494. }
  495. // Redraw
  496. this.draw();
  497. },
  498. // Shared activities list received
  499. sharedListReceived: function(activities) {
  500. // Ensure that an update is need
  501. if (this.activities.length == activities.length) {
  502. var len = this.activities.length;
  503. var found = 0;
  504. for(var i = 0 ; i < len ; i++) {
  505. for(var j = 0 ; j < len ; j++) {
  506. if (activities[i].activityId == this.activities[j].activityId && activities[i].users.length == this.activities[j].users.length) {
  507. found++;
  508. break;
  509. }
  510. }
  511. }
  512. if (found == len) {
  513. return;
  514. }
  515. }
  516. // Retrieve activities
  517. this.activities = activities;
  518. // Redraw
  519. this.draw();
  520. },
  521. // Draw screen
  522. draw: function() {
  523. // Resize content and set Journal empty in the middle
  524. var canvas_center = util.getCanvasCenter();
  525. this.$.empty.applyStyle("margin-left", (canvas_center.x-constant.sizeEmpty/4-10)+"px");
  526. var margintop = (canvas_center.y-constant.sizeEmpty/4-80);
  527. this.$.empty.applyStyle("margin-top", margintop+"px");
  528. this.$.message.applyStyle("margin-top", (margintop+70)+"px");;
  529. this.$.gotosettings.applyStyle("margin-top", (margintop+90)+"px");
  530. this.$.gotosettings.setText(l10n.get("MySettings"));
  531. this.$.refreshstate.applyStyle("margin-top", (margintop+90)+"px");
  532. this.$.refreshstate.setText(l10n.get("Refresh"));
  533. tutorial.setElement("owner", this.$.owner.getAttribute("id"));
  534. tutorial.setElement("server", this.$.server.getAttribute("id"));
  535. // Clean network icons
  536. var items = [];
  537. enyo.forEach(this.$.network.getControls(), function(item) { items.push(item); });
  538. for (var i = 0 ; i < items.length ; i++) { items[i].destroy(); };
  539. // List items to draw
  540. var canvas_center = util.getCanvasCenter();
  541. items = [];
  542. items.push({icon: this.$.owner, x:(canvas_center.x-constant.sizeNeighbor/2), y: (canvas_center.y-constant.sizeNeighbor/2), size: this.$.owner.getSize(), locked: true, child: []});
  543. if (this.$.server.getShowing())
  544. items.push({icon: this.$.server, size: this.$.server.getSize(), locked: false, child: []});
  545. // Create network icons for items
  546. this.createNetworkIcons(items);
  547. this.createWifiIcons(items);
  548. // Compute icons position
  549. var len = items.length;
  550. for(var i = 0 ; i < len ; i++) {
  551. // Set icon position
  552. var current = items[i];
  553. if (current.locked)
  554. continue;
  555. var hasChild = (current.child.length > 0) ? 1 : 0;
  556. var cacheData = this.findInCache(current);
  557. var maxx = canvas_center.dx-current.size-2*hasChild*current.size;
  558. current.x = (cacheData && cacheData.x < maxx) ? cacheData.x : current.size*hasChild + Math.floor(Math.random()*maxx);
  559. var maxy = canvas_center.dy-current.size-2*hasChild*current.size;
  560. current.y = (cacheData && cacheData.y < maxy) ? cacheData.y : current.size*hasChild + Math.floor(Math.random()*maxy);
  561. if (!cacheData) this.addToCache(current);
  562. // Set child position
  563. var childLen = current.child.length;
  564. for (var j = 0 ; j < childLen ; j++) {
  565. var child = current.child[j];
  566. var angle = (2.0*Math.PI)/childLen * j;
  567. child.x = current.x + current.size * Math.sin(angle);
  568. child.y = current.y - current.size * Math.cos(angle);
  569. }
  570. }
  571. var collisions = this.detectCollisions(items);
  572. if (collisions.length > 0) {
  573. this.solveCollisions(collisions, items);
  574. }
  575. // Draw all icons
  576. for (var i = 0 ; i < len ; i++) {
  577. var current = items[i];
  578. current.icon.applyStyle("margin-left", current.x+"px");
  579. current.icon.applyStyle("margin-top", current.y+"px");
  580. var childLen = current.child.length;
  581. for (var j = 0 ; j < childLen ; j++) {
  582. var child = current.child[j];
  583. child.applyStyle("margin-left", child.x+"px");
  584. child.applyStyle("margin-top", child.y+"px");
  585. }
  586. }
  587. // Filter
  588. this.filterNetwork();
  589. },
  590. // Create network icons fro items
  591. createNetworkIcons: function(items) {
  592. // Add user icons
  593. var len = this.users.length;
  594. var userIcons = [];
  595. var otherInTutorial = false;
  596. for (var i = 0 ; i < len ; i++) {
  597. var currentUser = this.users[i];
  598. if (currentUser.networkId != preferences.getNetworkId()) {
  599. var icon = this.$.network.createComponent({
  600. kind: "Sugar.Icon",
  601. icon: {directory: "icons", icon: "owner-icon.svg"},
  602. size: constant.sizeNeighbor,
  603. colorized: true,
  604. colorizedColor: currentUser.colorvalue,
  605. popupShow: enyo.bind(this, "showUserPopup"),
  606. popupHide: enyo.bind(this, "hideUserPopup"),
  607. data: currentUser
  608. },
  609. {owner: this}
  610. );
  611. icon.render();
  612. if (!otherInTutorial) {
  613. tutorial.setElement("other", icon.getAttribute("id"));
  614. otherInTutorial = true;
  615. }
  616. userIcons.push(icon);
  617. }
  618. }
  619. // Add activities icons
  620. len = this.activities.length;
  621. var userIconsInActivities = [];
  622. var activityInTutorial = false;
  623. for (var i = 0 ; i < len ; i++) {
  624. // Unknown activity, ignoe
  625. var currentActivity = this.activities[i];
  626. var activityInfo = preferences.getActivity(currentActivity.activityId);
  627. if (activityInfo == preferences.genericActivity) {
  628. continue;
  629. }
  630. // Add activity icon
  631. var icon = this.$.network.createComponent({
  632. kind: "Sugar.Icon",
  633. icon: {directory: activityInfo.directory, icon: activityInfo.icon},
  634. size: constant.sizeNeighbor,
  635. colorized: true,
  636. colorizedColor: currentActivity.colorvalue,
  637. popupShow: enyo.bind(this, "showActivityPopup"),
  638. popupHide: enyo.bind(this, "hideActivityPopup"),
  639. data: {shared: currentActivity, activity: activityInfo}
  640. },
  641. {owner: this}
  642. );
  643. icon.render();
  644. if (!activityInTutorial) {
  645. tutorial.setElement("activity", icon.getAttribute("id"));
  646. activityInTutorial = true;
  647. }
  648. // Add childs
  649. var childIcons = [];
  650. var childLen = currentActivity.users.length;
  651. for (var j = 0 ; j < childLen ; j++) {
  652. var userIconsLength = userIcons.length;
  653. for (var k = 0 ; k < userIconsLength ; k++) {
  654. var iconToTest = userIcons[k];
  655. if (currentActivity.users[j] == iconToTest.getData().networkId) {
  656. childIcons.push(iconToTest);
  657. userIconsInActivities.push(iconToTest);
  658. }
  659. }
  660. }
  661. items.push({icon: icon, size: icon.getSize(), locked: false, child: childIcons});
  662. }
  663. // Add icons alone
  664. var userIconsLength = userIcons.length;
  665. var childLen = userIconsInActivities.length;
  666. for (var i = 0 ; i < userIconsLength ; i++) {
  667. var found = false;
  668. var icon = userIcons[i];
  669. for (var j = 0 ; j < childLen && !found ; j++) {
  670. if (icon.getData().networkId == userIconsInActivities[j].getData().networkId) {
  671. found = true;
  672. }
  673. }
  674. if (!found) {
  675. items.push({icon: icon, size: icon.getSize(), locked: false, child: []});
  676. }
  677. }
  678. },
  679. // Detect collisions on drawing
  680. detectCollisions: function(items) {
  681. var collisions = [];
  682. var len = items.length;
  683. for (var i = 0 ; i < len ; i++) {
  684. for (var j = i+1 ; j < len ; j++) {
  685. var item0 = items[i];
  686. var item1 = items[j];
  687. var size0 = item0.size;
  688. var size1 = item1.size;
  689. var min0x = item0.x, max0x = item0.x+size0;
  690. var min0y = item0.y, max0y = item0.y+size0;
  691. var min1x = item1.x, max1x = item1.x+size1;
  692. var min1y = item1.y, max1y = item1.y+size1;
  693. if (item0.child.length > 0) {
  694. min0x -= size0;
  695. max0x += size0;
  696. min0y -= size0;
  697. max0y += size0;
  698. }
  699. if (item1.child.length > 0) {
  700. min1x -= size1;
  701. max1x += size1;
  702. min1y -= size1;
  703. max1y += size1;
  704. }
  705. if (!(max0x < min1x || min0x > max1x || min0y > max1y || max0y < min1y)) {
  706. if (item0.locked) {
  707. collisions.push(item1);
  708. } else {
  709. collisions.push(item0);
  710. }
  711. }
  712. }
  713. }
  714. return collisions;
  715. },
  716. // Move items to avoid collisions
  717. solveCollisions: function(collisions, items) {
  718. var stillCollide = true;
  719. var canvas_center = util.getCanvasCenter();
  720. for(var i = 0 ; stillCollide && i < constant.maxCollisionTry ; i++) {
  721. // Move all item with collision
  722. for(var j = 0 ; j < collisions.length ; j++) {
  723. // Move item
  724. var current = collisions[j];
  725. var hasChild = (current.child.length > 0) ? 1 : 0;
  726. current.x = current.size*hasChild + Math.floor(Math.random()*(canvas_center.dx-current.size-2*hasChild*current.size));
  727. current.y = current.size*hasChild + Math.floor(Math.random()*(canvas_center.dy-current.size-2*hasChild*current.size));
  728. // Move childs
  729. var childLen = current.child.length;
  730. for (var k = 0 ; k < childLen ; k++) {
  731. var child = current.child[k];
  732. var angle = (2.0*Math.PI)/childLen * k;
  733. child.x = current.x + current.size * Math.sin(angle);
  734. child.y = current.y - current.size * Math.cos(angle);
  735. }
  736. }
  737. // Detect again
  738. collisions = this.detectCollisions(items);
  739. stillCollide = (collisions.length > 0);
  740. }
  741. },
  742. // Filter network items
  743. filterNetwork: function() {
  744. var filter = (this.toolbar && !this.eeMode) ? this.toolbar.getSearchText().toLowerCase() : '';
  745. enyo.forEach(this.$.network.getControls(), function(item) {
  746. item.setDisabled(filter.length != 0 && item.data && item.data.name && item.data.name.toLowerCase().indexOf(filter) == -1);
  747. });
  748. this.$.server.setDisabled(filter.length != 0 && myserver.getServer().toLowerCase().indexOf(filter) == -1);
  749. },
  750. // Cache handling
  751. addToCache: function(item) {
  752. // Get name
  753. var data = item.icon.getData();
  754. var name;
  755. if (!data) {
  756. name = "server";
  757. } else if (data.networkId) {
  758. name = data.networkId;
  759. } else if (data.shared && data.shared.id) {
  760. name = data.shared.id;
  761. }
  762. // Add to cache
  763. var len = networkItemsCache;
  764. var found = false;
  765. for(var i = 0 ; i < len ; i++) {
  766. var networkItem = networkItemsCache[i];
  767. if (networkItem.name == name) {
  768. networkItem.x = x;
  769. networkItem.y = y;
  770. found = true;
  771. }
  772. }
  773. if (!found) {
  774. networkItemsCache.push({name: name, x: item.x, y: item.y, colorvalue: item.icon.getColorizedColor()});
  775. }
  776. },
  777. findInCache: function(item) {
  778. // Get name
  779. var data = item.icon.getData();
  780. var name;
  781. if (!data) {
  782. name = "server";
  783. } else if (data.networkId) {
  784. name = data.networkId;
  785. } else if (data.shared && data.shared.id) {
  786. name = data.shared.id;
  787. }
  788. // Return to cache
  789. var len = networkItemsCache.length;
  790. var found = false;
  791. for(var i = 0 ; i < len ; i++) {
  792. var networkItem = networkItemsCache[i];
  793. if (networkItem.name == name) {
  794. return networkItem;
  795. }
  796. }
  797. return null;
  798. },
  799. destroy: function() {
  800. this.inherited(arguments);
  801. clearTimeout(this.timer);
  802. }
  803. });
  804. // Class for neighborhood toolbar
  805. enyo.kind({
  806. name: "Sugar.NeighborhoodToolbar",
  807. kind: enyo.Control,
  808. components: [
  809. {name: "neighborsearch", kind: "Sugar.SearchField", onTextChanged: "filterNetwork", classes: "neighbor-filter-text"},
  810. {name: "helpbutton", kind: "Button", classes: "toolbutton help-button", title:"Help", ontap: "startTutorial"},
  811. {name: "radialbutton", kind: "Button", classes: "toolbutton view-desktop-button", title:"Home", title:"Home", ontap: "gotoDesktop"}
  812. ],
  813. // Constructor
  814. create: function() {
  815. this.inherited(arguments);
  816. this.localize();
  817. },
  818. rendered: function() {
  819. this.inherited(arguments);
  820. this.localize();
  821. },
  822. localize: function() {
  823. // Localize items
  824. this.$.neighborsearch.setPlaceholder(l10n.get("SearchNeighbor"));
  825. this.$.radialbutton.setNodeProperty("title", l10n.get("Home"));
  826. this.$.helpbutton.setNodeProperty("title", l10n.get("Tutorial"));
  827. },
  828. // Handle search text content
  829. getSearchText: function() {
  830. return this.$.neighborsearch.getText();
  831. },
  832. // Event handling
  833. gotoDesktop: function() {
  834. window.clearInterval(app.otherview.timer);
  835. util.vibrate();
  836. app.showView(constant.radialView);
  837. },
  838. filterNetwork: function() {
  839. app.otherview.filterNetwork();
  840. },
  841. startTutorial: function() {
  842. tutorial.setElement("radialbutton", this.$.radialbutton.getAttribute("id"));
  843. tutorial.setElement("neighborsearch", this.$.neighborsearch.getAttribute("id"));
  844. stats.trace(constant.viewNames[app.getView()], 'tutorial', 'start', null);
  845. tutorial.start();
  846. }
  847. });