/src/org/ishafoundation/archives/transcript/components/studio/concept/ConceptManagerDialog.mxml

http://transcriptstudio4isha.googlecode.com/ · Macromedia eXtensible Markup Language · 309 lines · 290 code · 19 blank · 0 comment · 0 complexity · 91044890032a7379ad56440267331c14 MD5 · raw file

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" alpha="2.0" layout="vertical" x="30" y="30" width="700" height="450" title="Concept Manager" horizontalAlign="center" creationComplete="init()" paddingLeft="0" paddingRight="0" paddingTop="0" roundedBottomCorners="false">
  3. <mx:Script>
  4. <![CDATA[
  5. import mx.events.CloseEvent;
  6. import org.ishafoundation.archives.transcript.components.generic.MessagePopUp;
  7. import org.ishafoundation.archives.transcript.util.Constants;
  8. import mx.utils.StringUtil;
  9. import org.ishafoundation.archives.transcript.components.generic.TextInputDialog;
  10. import mx.events.MenuEvent;
  11. import mx.collections.ArrayCollection;
  12. import mx.managers.DragManager;
  13. import mx.binding.utils.BindingUtils;
  14. import mx.controls.Alert;
  15. import mx.events.DragEvent;
  16. import name.carter.mark.flex.util.Utils;
  17. import mx.managers.PopUpManager;
  18. import org.ishafoundation.archives.transcript.model.ReferenceManager;
  19. [Bindable]
  20. private var referenceMgr:ReferenceManager;
  21. [Bindable]
  22. public var selectedConceptId:String;
  23. public static function createInstance(referenceMgr:ReferenceManager):ConceptManagerDialog {
  24. var result:ConceptManagerDialog = new ConceptManagerDialog();
  25. result.referenceMgr = referenceMgr;
  26. return result;
  27. }
  28. private function init():void {
  29. referenceMgr.getAllConcepts(function(conceptIds:Array):void {
  30. conceptList.dataProvider = conceptIds;
  31. }, function(msg:String):void {
  32. Alert.show(msg, "Failed to get all concepts");
  33. });
  34. }
  35. private function selectionChange(newConceptId:String):void {
  36. if (DragManager.isDragging) {
  37. return;
  38. }
  39. if (this.selectedConceptId != newConceptId) {
  40. trace("Selection changed to: " + newConceptId);
  41. this.selectedConceptId = newConceptId;
  42. }
  43. conceptList.selectedItem = newConceptId;
  44. }
  45. /**
  46. * Convenience method
  47. */
  48. private static function sort(arr:Array):Array {
  49. var result:Array = arr;
  50. arr.sort();
  51. return result;
  52. }
  53. private function closeMe():void {
  54. PopUpManager.removePopUp(this);
  55. }
  56. private function dragDropToSubTypeList(evt:DragEvent):void {
  57. if (!evt.dragSource.hasFormat("items")) {
  58. return;
  59. }
  60. evt.preventDefault();
  61. evt.currentTarget.hideDropFeedback(evt);
  62. var itemsArray:Array = evt.dragSource.dataForFormat("items") as Array;
  63. var draggedConceptId:String = itemsArray[0].toString();
  64. trace("Concept dropped: " + draggedConceptId);
  65. if (this.selectedConceptId == draggedConceptId) {
  66. Alert.show("Cannot assign concept as subtype of itself: " + draggedConceptId);
  67. }
  68. else {
  69. referenceMgr.addSubtype(this.selectedConceptId, draggedConceptId, function(added:Boolean):void {
  70. if (added) {
  71. refresh();
  72. }
  73. else {
  74. Alert.show("Already subtype: " + draggedConceptId);
  75. }
  76. }, function(msg:String):void {
  77. Alert.show(msg, "Failed to add subtype: " + draggedConceptId);
  78. });
  79. }
  80. }
  81. private function dragDropToSynonymList(evt:DragEvent):void {
  82. if (!evt.dragSource.hasFormat("items")) {
  83. return;
  84. }
  85. evt.preventDefault();
  86. evt.currentTarget.hideDropFeedback(evt);
  87. var itemsArray:Array = evt.dragSource.dataForFormat("items") as Array;
  88. var draggedConceptId:String = itemsArray[0].toString();
  89. trace("Concept dropped: " + draggedConceptId);
  90. if (this.selectedConceptId == draggedConceptId) {
  91. Alert.show("Cannot assign concept as synonym of itself: " + draggedConceptId);
  92. }
  93. else {
  94. referenceMgr.addSynonyms([this.selectedConceptId, draggedConceptId], function(added:Boolean):void {
  95. if (added) {
  96. refresh();
  97. }
  98. else {
  99. Alert.show("Already synonym: " + draggedConceptId);
  100. }
  101. }, function(msg:String):void {
  102. Alert.show(msg, "Failed to add synonym: " + draggedConceptId);
  103. });
  104. }
  105. }
  106. private function dragComplete(evt:DragEvent):void {
  107. conceptList.selectedItem = this.selectedConceptId;
  108. }
  109. private function generateCollectedConcepts(conceptId:String):String {
  110. if (conceptId == null) {
  111. return "";
  112. }
  113. else {
  114. return sort(referenceMgr.getCollectedConceptIds(conceptId).toArray()).toString().replace(/,/g, ", ")
  115. }
  116. }
  117. private function subTypeRemoveHandler():void {
  118. var subtypeId:String = subTypeList.selectedItem as String;
  119. referenceMgr.removeSubtype(this.selectedConceptId, subtypeId, function(removed:Boolean):void {
  120. if (removed) {
  121. refresh();
  122. }
  123. else {
  124. Alert.show("Subtype not found: " + subtypeId);
  125. }
  126. }, function(msg:String):void {
  127. Alert.show(msg, "Failed to remove subtype: " + subtypeId);
  128. });
  129. }
  130. private function synonymsLeaveHandler():void {
  131. referenceMgr.removeSynonym(this.selectedConceptId, function(removed:Boolean):void {
  132. if (removed) {
  133. refresh();
  134. }
  135. else {
  136. Alert.show("Synonym not found: " + this.selectedConceptId);
  137. }
  138. }, function(msg:String):void {
  139. Alert.show(msg, "Failed to remove synonym: " + this.selectedConceptId);
  140. });
  141. }
  142. private function refresh():void {
  143. subTypeList.executeBindings();
  144. synonymList.executeBindings();
  145. collectedConceptTextArea.executeBindings();
  146. }
  147. private function addConcept():void {
  148. var newConceptDialog:TextInputDialog = TextInputDialog.display(this, "Enter new concept", null, Constants.CONCEPT_ID_RESTRICTION);
  149. newConceptDialog.okButton.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
  150. var conceptId:String = Utils.normalizeSpace(newConceptDialog.textInput.text);
  151. if (conceptId != "") {
  152. var messagePopUp:MessagePopUp = createMessagePopup("Adding concept: " + conceptId);
  153. referenceMgr.addConcept(conceptId, function(returnVal:int):void {
  154. init();
  155. selectionChange(conceptId);
  156. if (returnVal == 0) {
  157. messagePopUp.enableOkButton("Concept already exists!");
  158. }
  159. else {
  160. messagePopUp.enableOkButton("Added");
  161. }
  162. },
  163. function(msg:String):void {
  164. messagePopUp.enableOkButton("Failed", msg);
  165. });
  166. }
  167. });
  168. }
  169. private function renameConcept():void {
  170. var oldConceptId:String = conceptList.selectedItem.toString();
  171. var thisObj:ConceptManagerDialog = this;
  172. referenceMgr.countConceptInstances(oldConceptId, function(count:int):void {
  173. if (count == 0) {
  174. renameConceptWithoutConfirmation(oldConceptId);
  175. }
  176. else {
  177. Alert.show("Are you sure you want to rename " + count + " instance(s)?", "Renaming concept: " + oldConceptId, Alert.OK | Alert.CANCEL, thisObj, function(evt:CloseEvent):void {
  178. if (evt.detail == Alert.OK) {
  179. renameConceptWithoutConfirmation(oldConceptId);
  180. }
  181. });
  182. }
  183. }, function(msg:String):void {
  184. Alert.show(msg, "Error");
  185. });
  186. }
  187. private function renameConceptWithoutConfirmation(oldConceptId:String):void {
  188. var renameConceptDialog:TextInputDialog = TextInputDialog.display(this, "Rename concept", oldConceptId, Constants.CONCEPT_ID_RESTRICTION);
  189. renameConceptDialog.okButton.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
  190. var newConceptId:String = Utils.normalizeSpace(renameConceptDialog.textInput.text);
  191. if (newConceptId != "") {
  192. if (oldConceptId == newConceptId) {
  193. Alert.show("Concept name unchanged: " + oldConceptId);
  194. return;
  195. }
  196. var messagePopUp:MessagePopUp = createMessagePopup("Renaming concept: " + oldConceptId + " to: " + newConceptId);
  197. referenceMgr.renameConcept(oldConceptId, newConceptId, function(returnVal:int):void {
  198. init();
  199. if (returnVal == 0) {
  200. selectionChange(null);
  201. messagePopUp.enableOkButton("Could not find concept!");
  202. }
  203. else {
  204. selectionChange(newConceptId);
  205. messagePopUp.enableOkButton("Renamed");
  206. }
  207. },
  208. function(msg:String):void {
  209. messagePopUp.enableOkButton("Failed", msg);
  210. });
  211. }
  212. });
  213. }
  214. private function removeConcept():void {
  215. var conceptId:String = conceptList.selectedItem.toString();
  216. referenceMgr.countConceptInstances(conceptId, function(count:int):void {
  217. if (count == 0) {
  218. var messagePopUp:MessagePopUp = createMessagePopup("Removing concept: " + conceptId);
  219. referenceMgr.removeConcept(conceptId, function(returnVal:int):void {
  220. init();
  221. selectionChange(null);
  222. messagePopUp.enableOkButton(returnVal == 0 ? "Could not find concept!" : "Removed");
  223. },
  224. function(msg:String):void {
  225. messagePopUp.enableOkButton("Failed", msg);
  226. });
  227. }
  228. else {
  229. Alert.show("Cannot remove concept because it appears at least once (" + count + " instance(s)) in all transcripts");
  230. }
  231. }, function(msg:String):void {
  232. Alert.show(msg, "Error");
  233. });
  234. }
  235. private function onMenuClick(evt:MenuEvent):void {
  236. var actionName:String = evt.item.@id;
  237. if ( actionName == "add" ) {
  238. addConcept();
  239. }
  240. else if ( actionName == "rename" ) {
  241. renameConcept();
  242. }
  243. else if ( actionName == "remove" ) {
  244. removeConcept();
  245. }
  246. }
  247. private function createMessagePopup(title:String):MessagePopUp {
  248. var result:MessagePopUp = MessagePopUp.display(this, title, "Please wait...", 250);
  249. result.okButton.enabled = false;
  250. return result;
  251. }
  252. ]]>
  253. </mx:Script>
  254. <mx:MenuBar id="myMenuBar" width="100%" labelField="@label" itemClick="onMenuClick(event)">
  255. <mx:XMLList id="menuData">
  256. <menuitem label="Concept">
  257. <menuitem id="add" label="Add..."/>
  258. <menuitem id="rename" label="Rename..." enabled="{conceptList.selectedItem != null}"/>
  259. <menuitem id="remove" label="Remove" enabled="{conceptList.selectedItem != null}"/>
  260. </menuitem>
  261. </mx:XMLList>
  262. </mx:MenuBar>
  263. <mx:HDividedBox width="100%" height="100%" horizontalGap="{Utils.DIVIDER_SIZE}">
  264. <mx:VBox width="33%" height="100%" minWidth="100">
  265. <mx:Label text="All Concepts"/>
  266. <mx:List id="conceptList" width="100%" height="100%" change="selectionChange(conceptList.selectedItem as String)" dragEnabled="true" dragDrop="dragDropToSubTypeList(event)" dragComplete="dragComplete(event)"/>
  267. </mx:VBox>
  268. <mx:VDividedBox width="67%" height="100%" minWidth="250" verticalGap="{Utils.DIVIDER_SIZE}">
  269. <mx:HDividedBox width="100%" height="60%" minHeight="100" horizontalGap="{Utils.DIVIDER_SIZE}" paddingBottom="10">
  270. <mx:VBox width="100%" height="100%" minWidth="130" horizontalAlign="center">
  271. <mx:Label text="Immediate subtypes" width="100%"/>
  272. <mx:List id="subTypeList" height="100%" width="100%" enabled="{this.selectedConceptId != null}" dropEnabled="true" dragDrop="dragDropToSubTypeList(event)" dataProvider="{this.selectedConceptId == null ? null : sort(this.referenceMgr.getConceptSubTypes(this.selectedConceptId).toArray())}"/>
  273. <mx:Button label="Remove" click="subTypeRemoveHandler()" enabled="{subTypeList.selectedItem != null}"/>
  274. </mx:VBox>
  275. <mx:VBox width="100%" height="100%" minWidth="100" horizontalAlign="center">
  276. <mx:Label text="Synonym group" width="100%"/>
  277. <mx:List id="synonymList" height="100%" width="100%" enabled="{this.selectedConceptId != null}" selectable="false" dropEnabled="true" dragDrop="dragDropToSynonymList(event)" dataProvider="{this.selectedConceptId == null ? null : sort(referenceMgr.getConceptSynonymsIncludingSelf(this.selectedConceptId).toArray())}"/>
  278. <mx:Button label="Leave Group" enabled="{(synonymList.dataProvider as ArrayCollection).length > 1}" click="synonymsLeaveHandler()"/>
  279. </mx:VBox>
  280. </mx:HDividedBox>
  281. <mx:VBox width="100%" height="40%" minHeight="100" paddingTop="10">
  282. <mx:Label text="Collected synonyms and subtypes"/>
  283. <mx:TextArea id="collectedConceptTextArea" width="100%" height="100%" editable="false" selectable="false" wordWrap="true" enabled="{this.selectedConceptId != null}" text="{generateCollectedConcepts(this.selectedConceptId)}"/>
  284. </mx:VBox>
  285. </mx:VDividedBox>
  286. </mx:HDividedBox>
  287. <mx:HBox>
  288. <mx:Button id="okButton" label="OK" click="{closeMe();referenceMgr.refreshAutoCompleteConcepts()}"/>
  289. </mx:HBox>
  290. </mx:TitleWindow>