Mercurial > hg > ccmiandroid
changeset 0:e0ee6ac3a45f
first import
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.classpath Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry kind="lib" path="libs/simple-xml-2.6.6.jar"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> + <classpathentry kind="lib" path="libs/android-support-v4.jar"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.project Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>ccmiandroid</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AndroidManifest.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest package="uk.ac.qmul.eecs.ccmi.activities" + android:versionCode="1" + android:versionName="1.0" xmlns:android="http://schemas.android.com/apk/res/android" > + + <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="9"/> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> + <uses-permission android:name="android.permission.VIBRATE"/> + + <application + android:icon="@drawable/ccmi_icon" + android:label="@string/app_name" > + <activity + android:name=".CcmiEditorAppActivity" + android:label="@string/app_name" + android:theme="@android:style/Theme.NoTitleBar" + android:screenOrientation="portrait" > + </activity> + + <activity + android:name="uk.ac.qmul.eecs.ccmi.activities.FileSelectorActivity$Open" + android:screenOrientation="portrait" + android:theme="@android:style/Theme.NoTitleBar" > + </activity> + + <activity + android:name="uk.ac.qmul.eecs.ccmi.activities.FileSelectorActivity$Save" + android:screenOrientation="portrait" + android:theme="@android:style/Theme.NoTitleBar" > + </activity> + + <activity android:name=".CcmiSplashActivity" android:screenOrientation="portrait" + android:theme="@android:style/Theme.NoTitleBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + + +</manifest> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.txt Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,40 @@ +CCmI Diagram Editor for Android +Copyright (C) 2012 Queen Mary University of London + +An Android(TM) App to access CCmI diagrams (.ccmi files) on touchscreen mobile devices. +Diagrams are presented in the same hierarchical structure as in the Audio View of CCmI Diagram Editor. +Users can navigate and edit the diagrams using audio and haptic feedback that these devices provide. +For more information see : http://ccmi.eecs.qmul.ac.uk/ + +The application has been tested on a Samsung Galaxy Note + +Screen Reader : +In order to get a fully accessibile experience, the screen reader TalkBack for Android, must be enabled, but the explore by touch +feature must be turned off. The screen reader is mainly necessary for audio feedback when typing on the screen keyboard. +Other screen readers might do as well, but have not been tested. +For more information about Talkback see the following link : +https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback + + +Keyboard : +The defualt keyboard didn't seem to get the screen reader to utter the keyboards letters when hovering on it. +On the contrary, the SoftKeyboard provided in the sample code of the Android SDK did, and it has therefore been included in this distribution +to ease the installation of a fully working App. +The SoftKeyboard is released under the Apache 2.0 License and it's Copyright of Google Inc. +Only the .apk and no source code is provided. Being the keyboard a separate program than the +CCmI Editor for Android, this is not incompatible with the license of this App. +If you want to access the SoftKeyboard code, you can install the Android SDK +For more information see : http://developer.android.com/sdk/index.html + + +Android Application Package File (APK): +the apk of this app is available at https://code.soundsoftware.ac.uk/projects/ccmiandroid/files + + + + +Android is a trademark of Google Inc. + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftKeyboard/LICENSE-2.0.txt Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftKeyboard/NOTICE.txt Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,195 @@ +Notice for all the files in this folder. +------------------------------------------------------------ + + + + Copyright (c) 2005-2008, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/assets/diagrams/Tube.ccmi Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,211 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<Diagram Name="Tube" PrototypeDelegate="uk.ac.qmul.eecs.ccmi.simpletemplate.SimpleShapePrototypePersistenceDelegate"> + <Prototypes> + <Node> + <Type>Stations</Type> + <ShapeType>Circle</ShapeType> + <Properties/> + </Node> + <Edge> + <Type>Central Line</Type> + <LineStyle>Solid</LineStyle> + <MinAttachedNodes>2</MinAttachedNodes> + <MaxAttachedNodes>2</MaxAttachedNodes> + </Edge> + <Edge> + <Type>Victoria Line</Type> + <LineStyle>Solid</LineStyle> + <MinAttachedNodes>2</MinAttachedNodes> + <MaxAttachedNodes>2</MaxAttachedNodes> + </Edge> + <Edge> + <Type>Jubilee Line</Type> + <LineStyle>Solid</LineStyle> + <MinAttachedNodes>2</MinAttachedNodes> + <MaxAttachedNodes>2</MaxAttachedNodes> + </Edge> + <Edge> + <Type>Piccadilly Line</Type> + <LineStyle>Solid</LineStyle> + <MinAttachedNodes>2</MinAttachedNodes> + <MaxAttachedNodes>2</MaxAttachedNodes> + </Edge> + <Edge> + <Type>Circle Line</Type> + <LineStyle>Solid</LineStyle> + <MinAttachedNodes>2</MinAttachedNodes> + <MaxAttachedNodes>2</MaxAttachedNodes> + </Edge> + </Prototypes> + <Components> + <Nodes> + <Node Name="Victoria" Type="Stations" id="1"> + <Position x="488.0" y="437.5"/> + </Node> + <Node Name="St James's Park" Type="Stations" id="2"> + <Position x="662.0" y="420.5"/> + </Node> + <Node Name="Westminster" Type="Stations" id="3"> + <Position x="868.0" y="429.0"/> + </Node> + <Node Name="Sloan Square" Type="Stations" id="4"> + <Position x="287.0" y="426.5"/> + </Node> + <Node Name="South Kensington" Type="Stations" id="5"> + <Position x="25.0" y="413.0"/> + </Node> + <Node Name="Green Park" Type="Stations" id="6"> + <Position x="480.0" y="192.0"/> + </Node> + <Node Name="Piccadilly Circus" Type="Stations" id="7"> + <Position x="754.0" y="179.0"/> + </Node> + <Node Name="Hyde Park Corner" Type="Stations" id="8"> + <Position x="214.0" y="214.0"/> + </Node> + <Node Name="Embankment" Type="Stations" id="9"> + <Position x="1056.0" y="427.0"/> + </Node> + <Node Name="Oxford Circus" Type="Stations" id="10"> + <Position x="626.0" y="21.5"/> + </Node> + <Node Name="Bond Street" Type="Stations" id="11"> + <Position x="406.0" y="19.5"/> + </Node> + <Node Name="Marble Arch" Type="Stations" id="12"> + <Position x="216.0" y="29.0"/> + </Node> + <Node Name="Tottenham Court Road" Type="Stations" id="13"> + <Position x="924.0" y="10.5"/> + </Node> + <Node Name="Lancaster Gate" Type="Stations" id="14"> + <Position x="34.0" y="17.0"/> + </Node> + <Node Name="Leicester Square" Type="Stations" id="15"> + <Position x="1017.0" y="175.5"/> + </Node> + <Node Name="Waterloo" Type="Stations" id="16"> + <Position x="957.0" y="637.0"/> + </Node> + <Node Name="Pimlico" Type="Stations" id="17"> + <Position x="489.0" y="638.0"/> + </Node> + </Nodes> + <Edges> + <Edge Name="Piccadilly Line 1" Type="Piccadilly Line" id="1"> + <Nodes> + <Node Head="" Label="" id="5"/> + <Node Head="" Label="" id="8"/> + </Nodes> + </Edge> + <Edge Name="Piccadilly Line 2" Type="Piccadilly Line" id="2"> + <Nodes> + <Node Head="" Label="" id="8"/> + <Node Head="" Label="" id="6"/> + </Nodes> + </Edge> + <Edge Name="Piccadilly Line 3" Type="Piccadilly Line" id="3"> + <Nodes> + <Node Head="" Label="" id="7"/> + <Node Head="" Label="" id="6"/> + </Nodes> + </Edge> + <Edge Name="Piccadilly Line 4" Type="Piccadilly Line" id="4"> + <Nodes> + <Node Head="" Label="" id="15"/> + <Node Head="" Label="" id="7"/> + </Nodes> + </Edge> + <Edge Name="Circle Line 1" Type="Circle Line" id="5"> + <Nodes> + <Node Head="" Label="" id="5"/> + <Node Head="" Label="" id="4"/> + </Nodes> + </Edge> + <Edge Name="Circle Line 2" Type="Circle Line" id="6"> + <Nodes> + <Node Head="" Label="" id="1"/> + <Node Head="" Label="" id="4"/> + </Nodes> + </Edge> + <Edge Name="Circle Line 3" Type="Circle Line" id="7"> + <Nodes> + <Node Head="" Label="" id="2"/> + <Node Head="" Label="" id="1"/> + </Nodes> + </Edge> + <Edge Name="Circle Line 4" Type="Circle Line" id="8"> + <Nodes> + <Node Head="" Label="" id="2"/> + <Node Head="" Label="" id="3"/> + </Nodes> + </Edge> + <Edge Name="Circle Line 5" Type="Circle Line" id="9"> + <Nodes> + <Node Head="" Label="" id="3"/> + <Node Head="" Label="" id="9"/> + </Nodes> + </Edge> + <Edge Name="Central Line 1" Type="Central Line" id="10"> + <Nodes> + <Node Head="" Label="" id="12"/> + <Node Head="" Label="" id="14"/> + </Nodes> + </Edge> + <Edge Name="Central Line 2" Type="Central Line" id="11"> + <Nodes> + <Node Head="" Label="" id="11"/> + <Node Head="" Label="" id="12"/> + </Nodes> + </Edge> + <Edge Name="Central Line 3" Type="Central Line" id="12"> + <Nodes> + <Node Head="" Label="" id="11"/> + <Node Head="" Label="" id="10"/> + </Nodes> + </Edge> + <Edge Name="Central Line 4" Type="Central Line" id="13"> + <Nodes> + <Node Head="" Label="" id="13"/> + <Node Head="" Label="" id="10"/> + </Nodes> + </Edge> + <Edge Name="Jubilee Line 1" Type="Jubilee Line" id="14"> + <Nodes> + <Node Head="" Label="" id="11"/> + <Node Head="" Label="" id="6"/> + </Nodes> + </Edge> + <Edge Name="Jubilee Line 2" Type="Jubilee Line" id="15"> + <Nodes> + <Node Head="" Label="" id="3"/> + <Node Head="" Label="" id="6"/> + </Nodes> + </Edge> + <Edge Name="Jubilee Line 3" Type="Jubilee Line" id="18"> + <Nodes> + <Node Head="" Label="" id="3"/> + <Node Head="" Label="" id="16"/> + </Nodes> + </Edge> + <Edge Name="Victoria Line 1" Type="Victoria Line" id="20"> + <Nodes> + <Node Head="" Label="" id="6"/> + <Node Head="" Label="" id="10"/> + </Nodes> + </Edge> + <Edge Name="Victoria Line 2" Type="Victoria Line" id="21"> + <Nodes> + <Node Head="" Label="" id="6"/> + <Node Head="" Label="" id="1"/> + </Nodes> + </Edge> + <Edge Name="Victoria Line 3" Type="Victoria Line" id="22"> + <Nodes> + <Node Head="" Label="" id="1"/> + <Node Head="" Label="" id="17"/> + </Nodes> + </Edge> + </Edges> + </Components> +</Diagram>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/uk/ac/qmul/eecs/ccmi/activities/BuildConfig.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,6 @@ +/** Automatically generated file. DO NOT MODIFY */ +package uk.ac.qmul.eecs.ccmi.activities; + +public final class BuildConfig { + public final static boolean DEBUG = true; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/uk/ac/qmul/eecs/ccmi/activities/R.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,112 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package uk.ac.qmul.eecs.ccmi.activities; + +public final class R { + public static final class attr { + } + public static final class color { + public static final int black=0x7f050004; + public static final int blue=0x7f050002; + public static final int green=0x7f050001; + public static final int red=0x7f050000; + public static final int white=0x7f050003; + } + public static final class drawable { + public static final int ccmi_icon=0x7f020000; + public static final int splashscreen=0x7f020001; + } + public static final class id { + public static final int CancelBtn=0x7f07000d; + public static final int RenameBtn=0x7f070013; + public static final int cancelBtn=0x7f070002; + public static final int checkBox=0x7f070014; + public static final int createBtn=0x7f070001; + public static final int deleteBtn=0x7f070009; + public static final int dialogCancelBtn1=0x7f070012; + public static final int dialogDeleteBtn=0x7f07000c; + public static final int dialogRenameBtn=0x7f07000b; + public static final int editArrowheadBtn=0x7f07000f; + public static final int editLabelBtn=0x7f07000e; + public static final int exitBtn=0x7f070003; + public static final int imageView1=0x7f07001b; + public static final int listView1=0x7f070018; + public static final int main_layout=0x7f070016; + public static final int modifiersBtn=0x7f070011; + public static final int noBtn=0x7f070006; + public static final int okBtn=0x7f070015; + public static final int openBtn=0x7f070005; + public static final int renameBtn=0x7f070008; + public static final int saveBtn=0x7f070004; + public static final int scrollButton=0x7f070017; + public static final int selectBtn=0x7f07000a; + public static final int selectionSpinner=0x7f07001a; + public static final int text_edit=0x7f070000; + public static final int txtHeader=0x7f070019; + public static final int unselectBtn=0x7f070010; + public static final int yesBtn=0x7f070007; + } + public static final class layout { + public static final int alert_dialog_add_property=0x7f030000; + public static final int alert_dialog_confirm_exit=0x7f030001; + public static final int alert_dialog_confirmation=0x7f030002; + public static final int alert_dialog_edit_edge=0x7f030003; + public static final int alert_dialog_edit_node=0x7f030004; + public static final int alert_dialog_edit_node_reference=0x7f030005; + public static final int alert_dialog_edit_node_unselect=0x7f030006; + public static final int alert_dialog_edit_property=0x7f030007; + public static final int alert_dialog_rename=0x7f030008; + public static final int checkbox_dialog=0x7f030009; + public static final int list_item_1=0x7f03000a; + public static final int main=0x7f03000b; + public static final int selection_dialog=0x7f03000c; + public static final int splash_screen=0x7f03000d; + public static final int text_dialog=0x7f03000e; + } + public static final class raw { + public static final int cancel=0x7f040000; + public static final int collapse=0x7f040001; + public static final int drag=0x7f040002; + public static final int editingmode=0x7f040003; + public static final int endoflist=0x7f040004; + public static final int error=0x7f040005; + public static final int expand=0x7f040006; + public static final int hookoff=0x7f040007; + public static final int hookon=0x7f040008; + public static final int jump=0x7f040009; + public static final int magnetoff=0x7f04000a; + public static final int magneton=0x7f04000b; + public static final int ok=0x7f04000c; + } + public static final class string { + public static final int app_name=0x7f060000; + public static final int cancelBtn=0x7f060007; + public static final int chooseBtn=0x7f06000d; + public static final int createBtn=0x7f060006; + public static final int deleteBtn=0x7f06000b; + public static final int editArrowheadBtn=0x7f060010; + public static final int editLabelBtn=0x7f06000f; + public static final int editTextContentDescription=0x7f060016; + public static final int exitBtn=0x7f060013; + public static final int exitMessage=0x7f060014; + public static final int modifiersBtn=0x7f060012; + public static final int noBtn=0x7f060003; + public static final int okBtn=0x7f060002; + public static final int openBtn=0x7f06000a; + public static final int renameBtn=0x7f060008; + public static final int saveBtn=0x7f060009; + public static final int scrollBtnDown=0x7f060004; + public static final int scrollBtnUp=0x7f060005; + public static final int selectBtn=0x7f06000c; + public static final int spinnerContentDescription=0x7f060017; + public static final int splash=0x7f060015; + public static final int toggleBtn=0x7f06000e; + public static final int unselectBtn=0x7f060011; + public static final int yesBtn=0x7f060001; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/project.properties Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/license.txt Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project.properties Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/alert_dialog_add_property.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + <EditText + android:id="@+id/text_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ems="10" + android:gravity="fill_horizontal" + android:inputType="text" + android:saveEnabled="false" + android:scrollHorizontally="true" + android:singleLine="true" + android:contentDescription="@string/editTextContentDescription" + android:textAppearance="?android:attr/textAppearanceMedium" > + <requestFocus /> + </EditText> + + <Button + android:id="@+id/createBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:tag="CREATE" + android:text="@string/createBtn" + android:textSize="40dp" + android:textStyle="bold" /> + + <Button + android:id="@+id/cancelBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:tag="CANCEL" + android:text="@string/cancelBtn" + android:textSize="40dp" + android:textStyle="bold" /> + + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/alert_dialog_confirm_exit.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + <Button + android:id="@+id/exitBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:soundEffectsEnabled="true" + android:text="@string/exitBtn" + android:tag="EXIT" + android:textSize="40dp" + android:textStyle="bold" /> + + <Button + android:id="@+id/saveBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:soundEffectsEnabled="true" + android:text="@string/saveBtn" + android:tag="SAVE" + android:textSize="40dp" + android:textStyle="bold" /> + + <Button + android:id="@+id/openBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:soundEffectsEnabled="true" + android:text="@string/openBtn" + android:tag="OPEN" + android:textSize="40dp" + android:textStyle="bold" /> + + <Button + android:id="@+id/noBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:soundEffectsEnabled="true" + android:text="@android:string/cancel" + android:tag="CANCEL" + android:textSize="40dp" + android:textStyle="bold" /> + + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/alert_dialog_confirmation.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <Button + android:id="@+id/yesBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/yesBtn" + android:textSize="40dp" + android:tag="YES" + android:textStyle="bold" /> + + <Button + android:id="@+id/noBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/noBtn" + android:tag="CANCEL" + android:textStyle="bold" + android:textSize="40dp"/> + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/alert_dialog_edit_edge.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + + <Button + android:id="@+id/renameBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/renameBtn" + android:tag="RENAME" + android:textStyle="bold" + android:textSize="40dp" /> + + <Button + android:id="@+id/deleteBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/deleteBtn" + android:tag="DELETE" + android:textStyle="bold" + android:textSize="40dp"/> + <Button + android:id="@+id/cancelBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:tag="CANCEL" + android:text="@string/cancelBtn" + android:textStyle="bold" android:textSize="40dp"/> + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/alert_dialog_edit_node.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + <Button + android:id="@+id/selectBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/selectBtn" + android:textSize="40dp" + android:tag="SELECT" + android:textStyle="bold" /> + + <Button + android:id="@+id/dialogRenameBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/renameBtn" + android:tag="RENAME" + android:textStyle="bold" + android:textSize="40dp" /> + + <Button + android:id="@+id/dialogDeleteBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/deleteBtn" + android:tag="DELETE" + android:textStyle="bold" + android:textSize="40dp"/> + <Button + android:id="@+id/CancelBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:tag="CANCEL" + android:text="@string/cancelBtn" + android:textStyle="bold" android:textSize="40dp"/> + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/alert_dialog_edit_node_reference.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + + <Button + android:id="@+id/editLabelBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/editLabelBtn" + android:tag="EDIT_LABEL" + android:textStyle="bold" + android:textSize="40dp" /> + + <Button + android:id="@+id/editArrowheadBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/editArrowheadBtn" + android:tag="EDIT_ARROWHEAD" + android:textStyle="bold" + android:textSize="40dp"/> + <Button + android:id="@+id/cancelBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:tag="CANCEL" + android:text="@string/cancelBtn" + android:textStyle="bold" android:textSize="40dp"/> + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/alert_dialog_edit_node_unselect.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + <Button + android:id="@+id/unselectBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/unselectBtn" + android:textSize="40dp" + android:tag="UNSELECT" + android:textStyle="bold" /> + + <Button + android:id="@+id/dialogRenameBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/renameBtn" + android:tag="RENAME" + android:textStyle="bold" + android:textSize="40dp" /> + + <Button + android:id="@+id/dialogDeleteBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/deleteBtn" + android:tag="DELETE" + android:textStyle="bold" + android:textSize="40dp"/> + <Button + android:id="@+id/CancelBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:tag="CANCEL" + android:text="@string/cancelBtn" + android:textStyle="bold" android:textSize="40dp"/> + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/alert_dialog_edit_property.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + <Button + android:id="@+id/renameBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/renameBtn" + android:textStyle="bold" + android:tag="RENAME" + android:textSize="40dp"/> + + <Button + android:id="@+id/modifiersBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/modifiersBtn" + android:tag="MODIFIERS" + android:textStyle="bold" + android:textSize="40dp" /> + + <Button + android:id="@+id/deleteBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/deleteBtn" + android:tag="DELETE" + android:textStyle="bold" + android:textSize="40dp" /> + <Button + android:id="@+id/dialogCancelBtn1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/cancelBtn" + android:tag="CANCEL" + android:textStyle="bold" + android:textSize="40dp" /> + + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/alert_dialog_rename.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + <EditText + android:id="@+id/text_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ems="10" + android:gravity="fill_horizontal" + android:inputType="text" + android:saveEnabled="false" + android:scrollHorizontally="true" + android:singleLine="true" + android:contentDescription="@string/editTextContentDescription" + android:textAppearance="?android:attr/textAppearanceMedium" > + <requestFocus /> + </EditText> + + <Button + android:id="@+id/RenameBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:soundEffectsEnabled="true" + android:tag="RENAME" + android:text="@string/renameBtn" + android:textSize="40dp" + android:textStyle="bold" /> + + <Button + android:id="@+id/CancelBtn" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:tag="CANCEL" + android:text="@string/cancelBtn" + android:textStyle="bold" + android:textSize="40dp"/> + + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/checkbox_dialog.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:tag="CHECKBOX" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <uk.ac.qmul.eecs.ccmi.accessibility.AccessibleCheckbox + android:id="@+id/checkBox" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:scrollbars="none" /> + + <Button + android:id="@+id/okBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@android:string/ok" + android:tag="OK" + android:textStyle="bold" + android:textSize="40dp" /> + <Button + android:id="@+id/cancelBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:tag="CANCEL" + android:text="@android:string/cancel" + android:textStyle="bold" + android:textSize="40dp" /> + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/list_item_1.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,10 @@ +<uk.ac.qmul.eecs.ccmi.accessibility.AccessibleTextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/text1" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:minHeight="68dip" + android:textAppearance="?android:attr/textAppearanceLarge" + android:gravity="center_vertical" + android:paddingLeft="6dip" + /> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/main.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/main_layout" + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + <Button + android:id="@+id/scrollButton" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:maxHeight="80dp" + android:minHeight="80dp" + android:text="@string/scrollBtnDown" + android:textSize="30dp" /> + + <LinearLayout + android:id="@+id/listView1" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layout_above="@+id/scrollButton" + android:layout_below="@+id/txtHeader" + android:scrollbars="none" + /> + + <TextView + android:id="@+id/txtHeader" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="#336699" + android:ellipsize="marquee" + android:gravity="center_vertical" + android:maxLines="1" + android:minHeight="?android:attr/listPreferredItemHeight" + android:padding="10dp" + android:paddingLeft="6dip" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textColor="#FFFFFF" + android:textSize="20dp" + android:textStyle="bold" /> + +</RelativeLayout> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/selection_dialog.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + <uk.ac.qmul.eecs.ccmi.accessibility.AccessibleSpinner + android:id="@+id/selectionSpinner" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:tag="SPINNER" + android:textStyle="bold" + android:textSize="40dp" + android:contentDescription="@string/spinnerContentDescription" /> + + <Button + android:id="@+id/selectBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/selectBtn" + android:tag="SELECT" + android:textStyle="bold" + android:textSize="40dp" /> + <Button + android:id="@+id/cancelBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:tag="CANCEL" + android:text="@string/cancelBtn" + android:textStyle="bold" + android:textSize="40dp" /> + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/splash_screen.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layout_gravity="center" + android:background="@color/black" > + + <ImageView + android:id="@+id/imageView1" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@drawable/splashscreen" + android:contentDescription="@string/splash" + /> +</LinearLayout> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/layout/text_dialog.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> + + <EditText + android:id="@+id/text_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ems="10" + android:gravity="fill_horizontal" + android:inputType="text" + android:saveEnabled="false" + android:scrollHorizontally="true" + android:singleLine="true" + android:contentDescription="@string/editTextContentDescription" + android:textAppearance="?android:attr/textAppearanceMedium" > + <requestFocus /> + </EditText> + + <Button + android:id="@+id/okBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:soundEffectsEnabled="true" + android:tag="OK" + android:text="@android:string/ok" + android:textSize="40dp" + android:textStyle="bold" /> + + <Button + android:id="@+id/cancelBtn" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:tag="CANCEL" + android:text="@android:string/cancel" + android:textStyle="bold" + android:textSize="40dp"/> + + </LinearLayout> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/values/colors.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> +<color name="red">#ff0000</color> +<color name="green">#00ff00</color> +<color name="blue">#0000ff</color> +<color name="white">#ffffff</color> +<color name="black">#a3a099</color> +</resources> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/values/strings.xml Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_name">CCmI Editor</string> + <string name="yesBtn">.... Yes ....</string> + <string name="okBtn">OK</string> + <string name="noBtn">.... No ....</string> + <string name="scrollBtnDown">Page Down</string> + <string name="scrollBtnUp">Roll Up</string> + <string name="createBtn">Create</string> + <string name="cancelBtn">Cancel</string> + <string name="renameBtn">Rename</string> + <string name="saveBtn">Save</string> + <string name="openBtn">Open</string> + <string name="deleteBtn">Delete</string> + <string name="selectBtn">Select</string> + <string name="chooseBtn">Choose</string> + <string name="toggleBtn">Toggle</string> + <string name="editLabelBtn">Edit Label</string> + <string name="editArrowheadBtn">Edit Arrow Head</string> + <string name="unselectBtn">Unselect</string> + <string name="modifiersBtn">Set Modifiers</string> + <string name="exitBtn"> Exit </string> + <string name="exitMessage">Click Exit to finish application!</string> + <string name="splash">Splash Screen</string> + <string name="editTextContentDescription">Text field:</string> + <string name="spinnerContentDescription">selection box:</string> +</resources> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/accessibility/AccessibilityService.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,202 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.accessibility; + +import java.util.EnumMap; +import java.util.Locale; + +import uk.ac.qmul.eecs.ccmi.activities.R; + +import android.content.Context; +import android.media.AudioManager; +import android.media.SoundPool; +import android.os.Vibrator; +import android.speech.tts.TextToSpeech; +import android.util.Log; + +/** + * Encloses all the services needed to implement a custom accessibility system. Text-to-speech synthesis, sound and + * device vibration. + * + */ +public class AccessibilityService { + private static final long VIBRATE_TIME = 200; + private static final float SPEECH_RATE = 2.0f; + private TextToSpeech tts; + private SoundPool soundPool; + private AudioManager audioManager; + private Vibrator vibrator; + private Context context; + private EnumMap<SoundEvent,Integer> soundIDs; + private boolean soundLoaded; + /** + * + * A list of events that have a sound associated. The sounds are built in and cannot be modified. + * + * + */ + public enum SoundEvent { + V_CANCEL, + V_COLLAPSE, + V_DRAG, + V_EDITING_MODE, + V_ENDOFLIST, + V_ERROR, + V_EXPAND, + V_HOOK_OFF, + V_HOOK_ON, + V_JUMP, + V_MAGNET_OFF, + V_MAGNET_ON, + V_OK + } + + private static AccessibilityService singleton; + + /** + * Creates an instance of {@code AccessibilityService}. It implements the singleton pattern, therefore + * successive calls to this method will always return the same object. + * + * @param context The context to use. Usually your {@code Application} or {@code Activity} object. + * + * @return a singleton instance of {@code AccessibilityService} + */ + public static AccessibilityService getInstance(Context context){ + if(singleton == null){ + singleton = new AccessibilityService(context); + } + return singleton; + } + + /** + * Constructs a new {@code AccessibilityService}. + * + * @param context The current context + */ + public AccessibilityService(Context context){ + soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0); + this.context = context; + audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); + soundIDs = new EnumMap<SoundEvent,Integer>(SoundEvent.class); + tts = new TextToSpeech(context, new TextToSpeech.OnInitListener(){ + @Override + public void onInit(int status) { + if (status == TextToSpeech.SUCCESS) { + int result = tts.setLanguage(Locale.UK); + if (result == TextToSpeech.LANG_MISSING_DATA + || result == TextToSpeech.LANG_NOT_SUPPORTED) { + Log.w("TEXT TO SPEECH", "Text to Speech UK language not supported"); + } + } + } + }); + tts.setSpeechRate(SPEECH_RATE); + vibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); + } + + /** + * Loads the built in sound library. This method must be called before any call to + * {@code playSound} or {@code stopSound}. + */ + public void loadSounds(){ + if(soundLoaded) + return; + soundIDs.put(SoundEvent.V_CANCEL,soundPool.load(context, R.raw.cancel, 1)); + soundIDs.put(SoundEvent.V_COLLAPSE,soundPool.load(context, R.raw.collapse, 1)); + soundIDs.put(SoundEvent.V_EXPAND,soundPool.load(context, R.raw.expand, 1)); + soundIDs.put(SoundEvent.V_ENDOFLIST,soundPool.load(context, R.raw.endoflist, 1)); + soundIDs.put(SoundEvent.V_OK,soundPool.load(context, R.raw.ok, 1)); + soundIDs.put(SoundEvent.V_DRAG,soundPool.load(context, R.raw.drag, 1)); + soundIDs.put(SoundEvent.V_EDITING_MODE,soundPool.load(context, R.raw.editingmode, 1)); + soundIDs.put(SoundEvent.V_ERROR,soundPool.load(context, R.raw.error, 1)); + soundIDs.put(SoundEvent.V_HOOK_OFF,soundPool.load(context, R.raw.hookoff, 1)); + soundIDs.put(SoundEvent.V_HOOK_ON,soundPool.load(context, R.raw.hookon, 1)); + soundIDs.put(SoundEvent.V_JUMP,soundPool.load(context, R.raw.jump, 1)); + soundIDs.put(SoundEvent.V_MAGNET_OFF,soundPool.load(context, R.raw.magnetoff, 1)); + soundLoaded = true; + } + + /** + * Plays the sound associated to a {@code SoundEvent}. + * + * @param event the event to play the sound of + * @param loop whether to play the sound in a continuous loop or not + */ + public void playSound(SoundEvent event, boolean loop){ + if(!soundLoaded) + throw new IllegalStateException("loadSounds() must be called before any call to playSound"); + float streamVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + streamVolume = streamVolume / audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + soundPool.play(soundIDs.get(event), streamVolume, streamVolume, 1, loop ? -1 : 0, 1f); + } + + /** + * Plays the sound associated to a {@code SoundEvent} once. This call is equivalent to + * {@code playSound(event,false)}. + * + * @param event the event to play the sound of + */ + public void playSound(SoundEvent event){ + playSound(event,false); + } + + /** + * Stop all the sounds being played at the moment of the call. Useful to stop a sound that is looping + * after a call to {@code playSound(event,true)}. + */ + public void stopSound(){ + if(!soundLoaded) + throw new IllegalStateException("loadSounds() must be called before any call to pauseSound"); + soundPool.autoPause(); + } + + /** + * Utters a text via android text to speech synthesizer + * + * @param text the string to be uttered + **/ + public void speak(String text){ + tts.speak(text, TextToSpeech.QUEUE_FLUSH, null); + } + + + /** + * Make the device vibrate + */ + public void vibrate(){ + vibrator.vibrate(VIBRATE_TIME); + } + + /** + * Dispose the resources allocated during initialization. To be called when the class + * is no longer needed by client classes. + */ + public void dispose(){ + /* dispose sound */ + for(SoundEvent evt : soundIDs.keySet()){ + soundPool.unload(soundIDs.get(evt)); + } + /* dispose tts */ + if(tts != null){ + tts.stop(); + tts.shutdown(); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/accessibility/AccessibleCheckbox.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,193 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.accessibility; + +import uk.ac.qmul.eecs.ccmi.activities.R; +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.widget.ArrayAdapter; +import android.widget.LinearLayout; +import android.widget.Spinner; + +/** + * + * A check box list that can be operated without looking at the display. + * + */ +public class AccessibleCheckbox extends LinearLayout{ + private NoClickSpinner spinner; + private AccessibilityService service; + private boolean[] checks; + + public AccessibleCheckbox(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public AccessibleCheckbox(Context context) { + super(context); + init(context); + } + + private void init(Context context){ + spinner = new NoClickSpinner(context); + spinner.setContentDescription("selection box: "); + spinner.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + setTag("CHECKBOX"); + addView(spinner); + } + + /** + * Sets the {@code accessibility} service for this class. + * + * @param service the {@code AccessibilityService} for this class + */ + public void setAccessibilityService(AccessibilityService service){ + this.service = service; + } + + /** + * Returns a reference to the {@code accessibility} service for this class. + * + * @return the {@code AccessibilityService} for this class + */ + public AccessibilityService getAccessibilityService(){ + return service; + } + + /** + * Sets the values to display to the user. + * + * @param values the values to display + * @param valueChecks The initial checks. If {@code valueChecks[i]} is {@code true} then {@code values[i]} will be + * checked when displayed to the user + */ + public void setValues(String[] values, boolean[] valueChecks){ + /* initialize the string array with the labels of the spinner, which are going to be between + * "<" and ">" if they are checked (according to valueChecks). + * checks is also initialized with valueChecks values, this will modified according + * to the user's selections and then returned by getValues() when the dialog is closed. + */ + final String[] markedValues = new String[values.length]; + checks = new boolean[valueChecks.length]; + for(int i=0; i<values.length; i++){ + checks[i] = valueChecks[i]; + markedValues[i] = (checks[i] ? "<"+values[i]+">" : values[i] ); + } + + spinner.setAdapter(new ArrayAdapter<String>(getContext(),R.layout.list_item_1,markedValues)); + + setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick(View view) { + spinner.setSelection((spinner.getSelectedItemPosition()+1) % spinner.getCount()); + if(service != null){ + service.speak(spinner.getSelectedItem().toString()+(checks[spinner.getSelectedItemPosition()] ? " " : " un")+"checked"); + } + } + }); + + setOnLongClickListener(new View.OnLongClickListener(){ + @Override + public boolean onLongClick(View view) { + int itemPosition = spinner.getSelectedItemPosition(); + checks[itemPosition] = !checks[itemPosition]; + if(checks[itemPosition]){ + markedValues[itemPosition] = "<"+markedValues[itemPosition]+">"; + }else{ + markedValues[itemPosition] = markedValues[itemPosition].replaceAll("(^<)|(>$)", ""); + } + if(service != null) + service.speak(spinner.getSelectedItem().toString()+(checks[spinner.getSelectedItemPosition()] ? "" : "un")+"checked"); + + spinner.setAdapter(new ArrayAdapter<String>(getContext(),R.layout.list_item_1,markedValues)); + spinner.setSelection(itemPosition); + return true; + } + }); + } + + /** + * Returns the checks of the current values. To be called after this checkbox has been displayed + * to the user to collect their checks. + * + * @return the current checks + */ + public boolean[] getChecks(){ + return checks; + } + + /** + * Returns the currently selected value of the list. + * + * @return the currently selected value of the list + */ + public String getSelectedValue(){ + return spinner.getSelectedItem().toString(); + } + + /** + * Returns the position in the list of the currently selected value. + * + * @return the position in the list of the currently selected value + */ + public int getSelectedValuePosition(){ + return spinner.getSelectedItemPosition(); + } + + /** + * This method is empty to prevent the screen reader to speak when clicking on this text view. + */ + @Override + public void sendAccessibilityEvent(int eventType){ + + } + + /** + * This method is empty to prevent the screen reader to speak when clicking on this text view. + */ + @Override + public void sendAccessibilityEventUnchecked(AccessibilityEvent event){ + + } + + private static class NoClickSpinner extends Spinner { + + public NoClickSpinner(Context context) { + super(context); + } + + public NoClickSpinner(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public NoClickSpinner(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent evt){ + return false; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/accessibility/AccessibleDialogBuilder.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,266 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.accessibility; + +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService.SoundEvent; +import uk.ac.qmul.eecs.ccmi.activities.R; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; + +public class AccessibleDialogBuilder { + private FragmentManager fragmentManager; + private AccessibilityService accessibilityService; + + public AccessibleDialogBuilder(FragmentManager fragmentManager) { + this.fragmentManager = fragmentManager; + } + + /** + * Sets the {@code AccessibilityService} for the dialogs. The call to this method must happen before + * any dialog is displayed. The dialogs will be then accessible through a {@code LayoutSonifier}. + * + * @param accessibilityService the {@code AccessibilityService} instance for this class. + */ + public void setAccessibilityService(AccessibilityService accessibilityService){ + this.accessibilityService = accessibilityService; + } + + /** + * Returns the instance of accessibility service in use. This can be useful to the client of this class to play + * speech and sound when showing and dismissing dialogs. + * + * @return a reference to the {@code AccessibilityService} class in use + */ + public AccessibilityService getAccessibilityService(){ + return accessibilityService; + } + + /** + * Displays an accessible dialog + * + * @param type ID for an XML layout resource to load (e.g., R.layout.main_page) + * @param tag the tag for this dialog. It's also used uttered out through the speech + * synthesizer to notify the user the dialog has been displayed + * @param buttonClickListener a listener that will be called when any of the buttons + * of the dialog will be pressed + */ + public void displayDialog(int type, String tag, ButtonClickListener buttonClickListener){ + AccessibleDialogFragment accessibleDialogFragment = new AccessibleDialogFragment(); + + accessibleDialogFragment.buttonClickListener = buttonClickListener; + accessibleDialogFragment.accessibilityService = accessibilityService; + + /* args to be used in onCreateDialog by the dialog fragment */ + Bundle args = new Bundle(); + args.putInt("dialogType", type); + args.putString("tag", tag); + accessibleDialogFragment.setArguments(args); + /* show the dialog */ + accessibleDialogFragment.show(fragmentManager,tag); + } + + /** + * Displays an accessible text dialog. The dialog has one text field for text input, and buttons + * to confirm or cancel your input. + * + * @param tag the tag for this dialog. It's also used uttered out through the speech + * synthesizer to notify the user the dialog has been displayed + * @param text optional text to set in the text field before shoing the dialog + * @param buttonClickListener a listener that will be called when any of the buttons + * of the dialog will be pressed + */ + public void displayTextDialog(String tag, String text, ButtonClickListener buttonClickListener){ + AccessibleDialogFragment accessibleDialogFragment = new AccessibleDialogFragment(); + + accessibleDialogFragment.buttonClickListener = buttonClickListener; + accessibleDialogFragment.accessibilityService = accessibilityService; + + /* args to be used in onCreateDialog by the dialog fragment */ + Bundle args = new Bundle(); + args.putInt("dialogType", R.layout.text_dialog); + args.putString("tag", tag); + if(text != null) + args.putString("text", text); + accessibleDialogFragment.setArguments(args); + /* show the dialog */ + accessibleDialogFragment.show(fragmentManager,tag); + } + + /** + * Displays an accessible selection dialog. The dialog has one selection box for selection input, and buttons + * to confirm or cancel your input. + * + * @param tag tag the tag for this dialog. It's also used uttered out through the speech + * synthesizer to notify the user the dialog has been displayed + * @param values the possible values of the selection box + * @param buttonClickListener a listener that will be called when any of the buttons + * of the dialog will be pressed + */ + public void displaySelectionDialog(String tag, String[] values, ButtonClickListener buttonClickListener ){ + AccessibleDialogFragment accessibleDialogFragment = new AccessibleDialogFragment(); + + accessibleDialogFragment.buttonClickListener = buttonClickListener; + accessibleDialogFragment.accessibilityService = accessibilityService; + accessibleDialogFragment.values = values; + + /* args to be used in onCreateDialog by the dialog fragment */ + Bundle args = new Bundle(); + args.putInt("dialogType", R.layout.selection_dialog); + args.putString("tag", tag); + accessibleDialogFragment.setArguments(args); + /* show the dialog */ + accessibleDialogFragment.show(fragmentManager,tag); + } + + /** + * Displays an accessible check box dialog. The dialog has one check box for selection input, and buttons + * to confirm or cancel your input. + * + * @param tag tag the tag for this dialog. It's also used uttered out through the speech + * synthesizer to notify the user the dialog has been displayed + * @param values the possible values that can be checked + * @param checks The initial checks. If {@code valueChecks[i]} is {@code true} then {@code values[i]} will be + * checked when displayed to the user + * @param buttonClickListener a listener that will be called when any of the buttons + * of the dialog will be pressed + */ + public void displayCheckDialog(String tag, String[] values, boolean[] checks, ButtonClickListener buttonClickListener){ + AccessibleDialogFragment accessibleDialogFragment = new AccessibleDialogFragment(); + + accessibleDialogFragment.buttonClickListener = buttonClickListener; + accessibleDialogFragment.accessibilityService = accessibilityService; + accessibleDialogFragment.values = values; + accessibleDialogFragment.checks = checks; + + /* args to be used in onCreateDialog by the dialog fragment */ + Bundle args = new Bundle(); + args.putInt("dialogType", R.layout.checkbox_dialog); + args.putString("tag", tag); + accessibleDialogFragment.setArguments(args); + /* show the dialog */ + accessibleDialogFragment.show(fragmentManager,tag); + } + + public static class AccessibleDialogFragment extends DialogFragment { + private String[] values; + private boolean[] checks; + private ButtonClickListener buttonClickListener; + private AccessibilityService accessibilityService; + + @Override + public Dialog onCreateDialog(final Bundle savedInstanceState) { + /* Get layout inflater */ + LayoutInflater inflater = getActivity().getLayoutInflater(); + /* inflate the view with layout and pass it to the builder for creation */ + ViewGroup layout = (ViewGroup)inflater.inflate(getArguments().getInt("dialogType"), null); + + if(values != null){ + if(checks == null){ //selection dialog + AccessibleSpinner spinner = (AccessibleSpinner)layout.findViewById(R.id.selectionSpinner); + spinner.setAccessibilityService(accessibilityService); + spinner.setAdapter(new ArrayAdapter<String>(getActivity(), R.layout.list_item_1 ,values)); + }else{ // check box dialog + AccessibleCheckbox checkbox = (AccessibleCheckbox)layout.findViewById(R.id.checkBox); + checkbox.setValues(values, checks); + checkbox.setAccessibilityService(accessibilityService); + } + } + if(getArguments().getString("text") != null){ + EditText textField = (EditText)layout.findViewById(R.id.text_edit); + textField.setText(getArguments().getString("text")); + } + + AlertDialog createdDialog = new AccessibleDialog(getActivity(),accessibilityService,layout); + createdDialog.setCancelable(false); + createdDialog.setCanceledOnTouchOutside(false); + + /* go through the layout and look for any buttons to hook them up with the button listener */ + for(int i=0; i< layout.getChildCount(); i++){ + if(layout.getChildAt(i) instanceof Button){ + Button b = (Button)layout.getChildAt(i); + b.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + buttonClickListener.onClick(v, AccessibleDialogFragment.this, getArguments().getString("tag")); + } + }); + } + } + + /* when showing a dialog a background sound is played in loop to notify the user they * + * have changed mode. More over the tag ( = the title) of the dialog is uttered out */ + accessibilityService.playSound(SoundEvent.V_EDITING_MODE, true); + accessibilityService.speak(getArguments().getString("tag")); + return createdDialog; + } + + @Override + public void onDismiss (DialogInterface dialog){ + /* when the dialog is dismissed the ambient sound is stopped to * + * notify the userhe is back in the non edit mode */ + accessibilityService.stopSound(); + } + + } + + /** + * A listener for the click of buttons in the dialogs displayed through {@code AccessibleDialogBuilder}. + */ + public interface ButtonClickListener { + /** + * When a button of a displayed dialog is clicked this method is called. + * + * @param v the clicked button + * @param dialogFragment the fragment used to show the dialog + * @param tag the tag of the dialog. Passed as argument to the display methods + */ + public void onClick(View v, DialogFragment dialogFragment, String tag); + } + + private static class AccessibleDialog extends AlertDialog { + AccessibilityService accessibilityService; + ViewGroup layout; + + private AccessibleDialog(Context context, AccessibilityService accessibilityService, ViewGroup layout) { + super(context); + this.accessibilityService = accessibilityService; + this.layout = layout; + setView(layout); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent evt){ + LayoutSonifier.getInstance().onTouch(layout, evt, accessibilityService); + return super.dispatchTouchEvent(evt); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/accessibility/AccessibleSpinner.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,74 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.accessibility; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.Spinner; + +/** + * + * The accessible spinner is designed to be accessible without looking at the display. A click on + * the spinner will not open a selection menu but will just switch the selected item, giving proper audio + * feedback of the performed action. + * + */ +public class AccessibleSpinner extends Spinner { + private AccessibilityService service; + + public AccessibleSpinner(Context context) { + super(context); + } + + public AccessibleSpinner(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public AccessibleSpinner(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void setAccessibilityService(AccessibilityService service){ + this.service = service; + } + + public AccessibilityService getAccessibilityService(){ + return service; + } + + /** + * Touching the spinner doesn't open a selection menu but just switches to the next item. The name of the next + * item is also uttered by the Android text-to-speech synthesizer. + * + * @param evt The motion event to be dispatched. + */ + @Override + public boolean dispatchTouchEvent(MotionEvent evt){ + if(evt.getAction() == MotionEvent.ACTION_UP){ + setSelection((getSelectedItemPosition()+1) % getCount()); + if(service != null){ + service.speak(getSelectedItem().toString()); + } + } + + return true; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/accessibility/AccessibleTextView.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,58 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.accessibility; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.accessibility.AccessibilityEvent; +import android.widget.TextView; + +/** + * + * A Text view used as argument of the {@code ArrayAdapter} constructor. It prevents the + * screen reader from talking too much when clicking on the list items. + * + */ +class AccessibleTextView extends TextView { + + public AccessibleTextView(Context context) { + super(context); + } + + public AccessibleTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public AccessibleTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * This method is empty to prevent the screen reader to speak when clicking on this text view. + */ + @Override + public void sendAccessibilityEvent(int eventType){} + + /** + * This method is empty to prevent the screen reader to speak when clicking on this text view. + */ + @Override + public void sendAccessibilityEventUnchecked(AccessibilityEvent event){} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/accessibility/LayoutSonifier.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,144 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.accessibility; + +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Spinner; +import android.widget.TextView; + +/** + * The {@code LayoutSonifier} provides the sonification of a {@code View}. When a {@code View} is sonified + * the user can swipe on it with their finger and receive audio and haptic cues about it. + * + * The {@code View} is rendered in audio by uttering (through the {@code Android} test to speech synthesizer) the content + * description, as per {@code getContentDescription()}. Furthermore, if the {@code View} is also a {@code TextView} + * the text is uttered too, right after the content description. Haptic rendering is just a vibration of the device. + * + * A {@code View} that is also a {@code ViewGroup} is recursively searched in its children until the non {@code ViewGruop} + * that is under the coordinates of the user touch is found. + * + * The way each {@code View} is sonified can be customized by subclassing this class and providing a custom + * implementation of {@code SonifyView()}. + * + */ +public class LayoutSonifier { + private static LayoutSonifier singleton; + /* in order not to utter the view's */ + private View lastTouchedView; + + /** + * static factory method enforces the existance of only one instance of this class at time (singleton) + * + * @return an instance of {@code LayoutSonifier} + */ + public static LayoutSonifier getInstance(){ + if(singleton == null) + singleton = new LayoutSonifier(); + return singleton; + } + + /* privatize the constructor to enforce singleton */ + protected LayoutSonifier(){} + + public boolean onTouch(View view, MotionEvent evt, AccessibilityService accessibilityService) { + if(accessibilityService == null) + throw new IllegalArgumentException("accessibilityService cannot be null"); + switch(evt.getAction()){ + case MotionEvent.ACTION_MOVE : { + if(evt.getPointerCount() > 1) // double finger is for scrolling + return false; + View newView = findView((ViewGroup)view,evt.getX(),evt.getY(),view.getLeft(),view.getTop()); + if(newView != lastTouchedView){ + sonifyView(newView,accessibilityService); + lastTouchedView = newView; + return false; + }else{ + return true; + } + } + case MotionEvent.ACTION_UP : { + lastTouchedView = null; + return false; + } + default : return false; + } + } + + /** + * This method is called when the view under the user's finger is found. The content + * description (as per {@code View.getContentDesctpion()} is uttered if not null, otherwise, + * if the View is a text view, the string returned by {@code TextView.getText()} is uttered. + * + * A vibration is triggered regardless of the type of the View. + * + * Subclasses can overwrite this method to provide their own sonification of the view touched + * by the user. Unless it's an {@code AccessibleSpinner} or a {@code AccessibleCheckbox} + * is never a {@code ViewGroup} as if a {@code ViewGroup} is met the view it contains + * are recursively searched for the one under the user's finger. + * + * @param v the view touched by the user + * @param accessibilityService the accessibility service used to sonify the view + */ + protected void sonifyView(View v, AccessibilityService accessibilityService){ + if(v == null) + return; + if(v instanceof TextView ){ + accessibilityService.vibrate(); + CharSequence contentDescription = v.getContentDescription(); + /* if the view has accessibility content description set, use it */ + if(contentDescription != null ) + accessibilityService.speak(contentDescription.toString() + + ((v instanceof TextView) ? ((TextView)v).getText() : "") ); + else + accessibilityService.speak(((TextView)v).getText().toString()); + }else if(v instanceof AccessibleCheckbox){ + AccessibleCheckbox ab = (AccessibleCheckbox)v; + boolean isChecked = ab.getChecks()[ab.getSelectedValuePosition()]; + accessibilityService.vibrate(); + accessibilityService.speak(ab.getSelectedValue()+ (isChecked ? ", checked" : ", unchecked")); + }else if (v instanceof Spinner){ + accessibilityService.vibrate(); + accessibilityService.speak(v.getContentDescription()+" "+((Spinner)v).getSelectedItem()); + } + } + + private static View findView(ViewGroup viewGroup, float x, float y, float offsetX, float offsetY){ + x-= offsetX; + y-= offsetY; + + /* look for other views which one is under the finger of the user */ + for(int i=0; i<viewGroup.getChildCount(); i++){ + View v = viewGroup.getChildAt(i); + if(y > v.getTop() && y < (v.getTop()+v.getHeight()) && + x > v.getLeft() && x < (v.getLeft()+v.getWidth()) ){ + if(v instanceof ViewGroup){ + if(v instanceof AccessibleSpinner || v instanceof AccessibleCheckbox) + return v; + return findView((ViewGroup)v,x,y,v.getLeft(),v.getTop()); + }else{ + return v; + } + } + } + return null; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/activities/AccessibleActivity.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,215 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.activities; + +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService; +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService.SoundEvent; +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibleDialogBuilder; +import uk.ac.qmul.eecs.ccmi.accessibility.LayoutSonifier; +import android.content.pm.PackageManager; +import android.media.AudioManager; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.TextView; + +/** + * An abstract accessible activity, displaying items of a list in a ListView and a text header. + */ +public abstract class AccessibleActivity extends FragmentActivity { + private TextView header; + private ViewGroup mainLayout; + private Button scrollButton; + private boolean activityNameUttered = false; + + /** + * the class used to generate audio and tactile cues when exploring the activity + */ + protected AccessibilityService accessibilityService; + /** + * The list item list of the activity + */ + protected ListView list; + /** + * used to generate dialogs when the user clicks or long-clicks on an item + */ + protected AccessibleDialogBuilder dialogBuilder; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Set the hardware buttons to control the music + this.setVolumeControlStream(AudioManager.STREAM_MUSIC); + + /* makes the activity run on a full screen. */ + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + mainLayout = (ViewGroup)getLayoutInflater().inflate(R.layout.main, null); + setContentView(mainLayout); + + dialogBuilder = new AccessibleDialogBuilder(this.getSupportFragmentManager()); + + /* place the main list in the view */ + LinearLayout listLayout = (LinearLayout)findViewById(R.id.listView1); + /* avoid scrolling upon touching, we rather want the user to hear the content */ + list = new ListView(this){ + @Override + public boolean dispatchTouchEvent(MotionEvent ev){ + //returning true prevents the scrolling action on the listview + if(ev.getAction()==MotionEvent.ACTION_MOVE && ev.getPointerCount() == 1) + return true; + return super.dispatchTouchEvent(ev); + } + + @Override + public void setAdapter(final ListAdapter adapter){ + super.setAdapter(adapter); + if(scrollButton != null){ + post(new Runnable(){ // need to be posted in order to work, as the list is not rendered yet at this point + public void run(){ + boolean thereIsMore = (list.getLastVisiblePosition() < adapter.getCount()-1); + scrollButton.setEnabled(thereIsMore); + scrollButton.setContentDescription( + thereIsMore ? "scroll button" : "scroll button disabled"); + } + }); + } + } + }; + list.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + listLayout.addView(list); + + /* init header with a button to scroll down an up the list */ + header = (TextView)findViewById(R.id.txtHeader); + scrollButton = (Button)findViewById(R.id.scrollButton); + + /* if the device supports double finger touch screen then the user will scroll by + * swiping with two fingers. Otherwise a button at the very bottom will be created that will scroll the + * list of one item each time it's pressed and when the bottom is reached it will scroll up to the top. + */ + if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)){ + mainLayout.removeView(scrollButton); + scrollButton = null; + }else{ + scrollButton.setOnClickListener(new View.OnClickListener() { + boolean doOnceMore = true; + + @Override + public void onClick(View v) { + if(list.getLastVisiblePosition() == list.getCount()-1){ + /* when the last item becomes visible it's not entirely visible. So don't go immediately * + * to the top but let the user scroll once more and make it entirely visible */ + if(doOnceMore){ + doOnceMore = false; + accessibilityService.playSound(SoundEvent.V_OK, false); + list.smoothScrollToPosition(list.getLastVisiblePosition()); + scrollButton.setText(R.string.scrollBtnUp); + }else{ + doOnceMore = true; + accessibilityService.playSound(SoundEvent.V_ENDOFLIST, false); + list.smoothScrollToPosition(0); + scrollButton.setText(R.string.scrollBtnDown); + } + }else{ + accessibilityService.playSound(SoundEvent.V_OK, false); + list.smoothScrollToPosition(list.getLastVisiblePosition()); + } + } + }); + } + } + + @Override + protected void onResume(){ + super.onResume(); + accessibilityService = new AccessibilityService(this); + accessibilityService.loadSounds(); + dialogBuilder.setAccessibilityService(accessibilityService); + + } + + /** + * When the activity is resumed the header text is uttered thought the text to speech sinthesizer + */ + @Override + public void onPostResume(){ + super.onPostResume(); + header.post(new Runnable(){ + @Override + public void run() { + if(!activityNameUttered){ + accessibilityService.speak(getName()+". Displaying "+getHeaderText()); + activityNameUttered = true; + }else{ + accessibilityService.speak("Displaying "+getHeaderText()); + } + } + }); + } + + @Override + protected void onPause(){ + super.onPause(); + accessibilityService.stopSound(); + accessibilityService.dispose(); + dialogBuilder.setAccessibilityService(null); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent evt){ + //returning true prevents the scrolling action on the listview + if(evt.getAction()==MotionEvent.ACTION_MOVE && evt.getPointerCount() == 1){ + LayoutSonifier.getInstance().onTouch(mainLayout, evt, accessibilityService); + return true; + } + + if(evt.getAction() == MotionEvent.ACTION_UP) + LayoutSonifier.getInstance().onTouch(mainLayout, evt, accessibilityService); + return super.dispatchTouchEvent(evt); + } + + /** + * Set the header text. The text is uttered when the user hover over the header. + * + * @param headerText the header text + */ + protected void setHeaderText(CharSequence headerText){ + header.setText(headerText); + } + + /** + * Returns the header text. The text is uttered when the user hover over the header. + * + * @return the header text + */ + protected CharSequence getHeaderText(){ + return header.getText(); + } + + public abstract String getName(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/activities/CcmiEditorAppActivity.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,214 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.activities; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import org.simpleframework.xml.Serializer; +import org.simpleframework.xml.core.Persister; + +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService; +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService.SoundEvent; +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibleDialogBuilder; +import uk.ac.qmul.eecs.ccmi.xmlparser.Diagram; +import android.content.Intent; +import android.content.res.AssetManager; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemLongClickListener; +import android.widget.ArrayAdapter; + +/** + * + * The main activity. It displays the diagram through the hierarchical view + * of the <a href="http://ccmi.eecs.qmul.ac.uk"> CCmI Diagram Editor </a> + * + */ +public class CcmiEditorAppActivity extends AccessibleActivity implements + OnItemClickListener, OnItemLongClickListener, TreeNavigation.Updateable { + private final static int OPEN_REQUEST = 1; + private final static int SAVE_REQUEST = 2; + private final static String CCMI_EXTENSION = ".ccmi"; + + private Diagram diagram; + private TreeNavigation navigation; + + private String file; + private InputStream in; + + public String getName(){ + return ""; + } + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + list.setOnItemClickListener(this); + list.setOnItemLongClickListener(this); + + /* init assets */ + AssetManager assetManager = getAssets(); + try { + file = assetManager.list("diagrams")[0]; + in = assetManager.open("diagrams/"+file); + readXML(in); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + /* create a new list and display it */ + @Override + public void update(){ + /* header */ + setHeaderText(navigation.getCurrentItemName()); + /* list */ + ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.list_item_1,navigation.getCurrentChildList()); + list.setAdapter(adapter); + } + + /*----- listeners to implement the navigation ----*/ + @Override + public void onItemClick(AdapterView<?> av, View v, int pos, long id) { + if(!navigation.goNext(pos)){ + accessibilityService.playSound(AccessibilityService.SoundEvent.V_ERROR); + return; + } + accessibilityService.playSound(AccessibilityService.SoundEvent.V_EXPAND); + accessibilityService.speak("Displaying " + getHeaderText()); + } + + /** + * The activity listens to long clicks performed on the list view. + * + * When a user long clicks an item, a dialog is displayed accordingly. For example if the types of nodes and + * edges are listed when the user long clicks, then a dialog for insertion of a new node or edge is displayed. + */ + @Override + public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { + boolean doneSomething = navigation.getController().performEditAction(parent, view, position, id, this); + if(!doneSomething) + accessibilityService.playSound(AccessibilityService.SoundEvent.V_ERROR); + return doneSomething; + } + + /** + * When the back button is pressed the activity will cursor back in the tree + * view, which means the parent of the currently displayed items will be displayed + * together with its siblings. + */ + @Override + public void onBackPressed() { + if(navigation.goPrevious()){ + accessibilityService.playSound(SoundEvent.V_COLLAPSE); + accessibilityService.speak("Displaying "+getHeaderText()); + update(); + }else{ + accessibilityService.playSound(SoundEvent.V_EDITING_MODE, true); + dialogBuilder.displayDialog(R.layout.alert_dialog_confirm_exit,"Exit Dialog",new AccessibleDialogBuilder.ButtonClickListener() { + @Override + public void onClick(View v, DialogFragment dialogFragment, String tag) { + if("EXIT".equals(v.getTag())){ + accessibilityService.speak(getResources().getString(R.string.exitMessage)); + finish(); + }else if("CANCEL".equals(v.getTag())){ + accessibilityService.speak("Cancel"); + accessibilityService.stopSound(); + dialogFragment.dismiss(); + }else if("OPEN".equals(v.getTag())){ + /* start the activity to open a file */ + Intent intent = new Intent(CcmiEditorAppActivity.this, FileSelectorActivity.Open.class); + intent.putExtra("extension", CCMI_EXTENSION); + startActivityForResult(intent,OPEN_REQUEST); + dialogFragment.dismiss(); + }else if("SAVE".equals(v.getTag())){ + Intent intent = new Intent(CcmiEditorAppActivity.this, FileSelectorActivity.Save.class); + intent.putExtra("extension", CCMI_EXTENSION); + startActivityForResult(intent,SAVE_REQUEST); + dialogFragment.dismiss(); + } + } + }); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if(resultCode == RESULT_OK){ + if(requestCode == OPEN_REQUEST){ + try { + InputStream in = new FileInputStream(new File(data.getData().getPath())); + readXML(in); + } catch (Exception e) { + accessibilityService.playSound(SoundEvent.V_ERROR); + accessibilityService.speak("File could not be open"); + } + }else if(requestCode == SAVE_REQUEST){ + try { + String filePath = data.getData().getPath(); + String diagramName = data.getData().getLastPathSegment(); + /* make sure the extension is .ccmi */ + if(!filePath.endsWith(CCMI_EXTENSION)||(CCMI_EXTENSION.equals(diagramName))) + filePath += CCMI_EXTENSION; + + /* make sure diagram name doesn't have trailing .ccmi, unless the name is just ".ccmi" */ + if(diagramName.endsWith(CCMI_EXTENSION) && !(CCMI_EXTENSION.equals(diagramName))){ + diagramName = diagramName.substring(0, diagramName.length()-CCMI_EXTENSION.length()); + } + + diagram.setName(diagramName); + OutputStream out = new FileOutputStream(new File(filePath)); + saveXML(out); + } catch (Exception e) { + accessibilityService.playSound(SoundEvent.V_ERROR); + accessibilityService.speak("File could not be saved"); + } + } + } + } + + private void saveXML(OutputStream out) throws Exception { + Serializer serializer = new Persister(); + serializer.write(diagram, out); + out.close(); + navigation = new TreeNavigation(diagram,dialogBuilder,this); + update(); + accessibilityService.playSound(SoundEvent.V_OK); + accessibilityService.speak("Filed saved"); + } + + private void readXML(InputStream in) throws Exception { + Serializer serializer = new Persister(); + diagram = serializer.read(Diagram.class, in); + in.close(); + navigation = new TreeNavigation(diagram,dialogBuilder,this); + update(); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/activities/CcmiSplashActivity.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,71 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.activities; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +/** + * Splash screen Activity. Shows the splash screen for {@code SPLASH_DELAY} millisecond + * and then starts the main Activity + */ +public class CcmiSplashActivity extends Activity { + /** + * number of millisecond the splash is displayed before starting the main Activity + */ + public static final int SPLASH_DELAY = 2000; + private long ms=0; + private boolean splashActive = true; + private boolean paused=false; + + /** Called when the activity is first created. */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.splash_screen); + Thread t = new Thread() { + @Override + public void run() { + try { + while (splashActive && ms < SPLASH_DELAY) { + if(!paused) + ms=ms+100; + sleep(100); + } + } catch(Exception e) {e.printStackTrace();} + finally { + Intent intent = new Intent(CcmiSplashActivity.this, CcmiEditorAppActivity.class); + startActivity(intent); + finish(); + } + } + }; + t.start(); + } + + /** + * Pressing the back button on the splash screen doesn't kill the activity. The user must wait for the + * main activity to be displayed before exiting the application. + */ + @Override + public void onBackPressed() {} +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/activities/FileSelectorActivity.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,251 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.activities; + +import java.io.File; +import java.io.FileFilter; +import java.util.ArrayList; +import java.util.List; + +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService.SoundEvent; +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService; +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibleDialogBuilder; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.support.v4.app.DialogFragment; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemLongClickListener; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.TextView; + +/** + * An abstract activity for file selection. + * + * The file system is shown as follows: the current directory is displayed + * on a the header and all the files or folder contained in it are displayed in a list view. Clicking on a list item + * will only take effect if the item is a directory. The selected directory will become the current directory. + * In order to select the parent directory a click on the back button is needed. + * + * Being an {@code AccessibleActivity} the view can be explored though sound and haptics by hovering on it. + * in order to scroll the list a double-finger scroll is required or, if the device does not support multitouch, a + * scroll button will appear on the bottom for scrolling. + * + */ +public abstract class FileSelectorActivity extends AccessibleActivity implements + OnItemClickListener, OnItemLongClickListener { + + private File[] currentFileList; + private File currentFile; + private FileFilter fileFilter; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + list.setOnItemClickListener(this); + list.setOnItemLongClickListener(this); + + final CharSequence extension = getIntent().getCharSequenceExtra("extension"); + fileFilter = new FileFilter() { + /* only accepts directories and .ccmi files */ + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } + + if(extension == null) + return true; + else + return file.getName().endsWith(extension.toString()); + } + }; + + update(new File(Environment.getExternalStorageDirectory().getPath())); + } + + /* false if new list is empty, true otherwise */ + private boolean update(File file) { + + currentFile = file; + currentFileList = currentFile.listFiles(fileFilter); + + setHeaderText(currentFile.getName()); + List<String> names = new ArrayList<String>(currentFileList.length); + + for (int i = 0; i < currentFileList.length; i ++) { + String fileName = currentFileList[i].getName(); + if (currentFileList[i].isDirectory()) { + fileName = "/" + fileName; + } + names.add(fileName); + } + + list.setAdapter(new ArrayAdapter<String>(this, + R.layout.list_item_1, names)); + + return !names.isEmpty(); + } + + @Override + public void onItemClick(AdapterView<?> av, View v, int position, long id) { + // the first thing in list is parent directory, so we must offset it + File selectedFile = currentFileList[position]; + if (selectedFile.isDirectory()) { + if(selectedFile.listFiles(fileFilter).length == 0){ + accessibilityService.playSound(SoundEvent.V_ERROR); + accessibilityService.speak("Directory empty"); + } + boolean anyItems = update(selectedFile); + accessibilityService.playSound(AccessibilityService.SoundEvent.V_EXPAND); + if(anyItems) + accessibilityService.speak("Displaying " + getHeaderText()); + else + accessibilityService.speak("Displaying " + getHeaderText()+". Empty"); + }else{ + accessibilityService.playSound(SoundEvent.V_ERROR); + } + } + + /** + * To be implemented by subclasses. The long click represent the trigger of an operation on the selected file. + */ + @Override + public abstract boolean onItemLongClick(AdapterView<?> av, View v, int position, long id); + + /** + * On pressing the back button, the parent of the current directory will be displayed. + */ + @Override + public void onBackPressed() { + if(currentFile.getAbsolutePath().equals(Environment.getExternalStorageDirectory().getPath())){ + setResult(RESULT_CANCELED); + super.onBackPressed(); // finish the activity + return; + } + + File parent = currentFile.getParentFile(); + update(parent); + accessibilityService.playSound(SoundEvent.V_COLLAPSE); + accessibilityService.speak("Displaying "+getHeaderText()); + } + + /** + * A {@code FileSelectorActivity} for opening a file. A long click on an item will open a confirmation dialog + * to open the file. If the user confirms, the activity will finish and set a result intent with the Uri + * of the opened file. + */ + public static class Open extends FileSelectorActivity { + /** + * Displays a confirmation dialog to open the file + */ + @Override + public boolean onItemLongClick(AdapterView<?> av, View v, int position, long id) { + final File selectedFile = super.currentFileList[position]; + if(selectedFile.isDirectory()){ + accessibilityService.playSound(SoundEvent.V_ERROR); + return true; + } + + dialogBuilder.displayDialog(R.layout.alert_dialog_confirmation, "Do you want to Open File "+(((TextView)v).getText())+" ?", new AccessibleDialogBuilder.ButtonClickListener(){ + @Override + public void onClick(View v, DialogFragment dialogFragment, String dialogTag){ + if("YES".equals(v.getTag())){ // YES + dialogFragment.dismiss(); + Intent resultIntent = new Intent(); + resultIntent.setData(Uri.fromFile(selectedFile)); + setResult(RESULT_OK, resultIntent); + finish(); + }else{ // NO + dialogFragment.dismiss(); + accessibilityService.playSound(SoundEvent.V_CANCEL); + accessibilityService.speak(getHeaderText().toString()); + } + } + }); + return true; + } + + @Override + public String getName(){ + return "Select File to Open"; + } + } + + /** + * A {@code FileSelectorActivity} for saving a file. A long click on an item will open a text dialog + * to enter the name of the file to save. If the user clicks on a file list item, the text field will + * be filled with the name thereof. + */ + public static class Save extends FileSelectorActivity { + + /** + * When the user long-clicks on an item a text dialog for the user to enter the file name appears. + */ + @Override + public boolean onItemLongClick(AdapterView<?> av, View v, int position, long id) { + final File selectedFile = super.currentFileList[position]; + + final String text = selectedFile.isDirectory() ? "" : selectedFile.getName(); + dialogBuilder.displayTextDialog("Enter File name ", text, new AccessibleDialogBuilder.ButtonClickListener(){ + @Override + public void onClick(View v, DialogFragment dialogFragment, String dialogTag) { + Object buttonTag = v.getTag(); + if("OK".equals(buttonTag)){ + EditText editText = (EditText)dialogFragment.getDialog().findViewById(R.id.text_edit); + String text = editText.getText().toString().trim(); + + if(text.length() == 0){ + accessibilityService.playSound(SoundEvent.V_ERROR); + accessibilityService.speak("File name cannot be empty"); + return; + } + + /* if the selected file was a directory, then concat it with the text entered by the user * + * if it was a file, then concat the directory where the file was with the text entered by the user * + * In the latter the user can overwrite a file just by clicking OK without entering any text */ + Uri dir = selectedFile.isDirectory() ? Uri.fromFile(selectedFile) : Uri.fromFile(selectedFile.getParentFile()); + + Intent resultIntent = new Intent(); + resultIntent.setData(Uri.withAppendedPath(dir, text)); + setResult(RESULT_OK, resultIntent); + finish(); + }else{ + dialogFragment.dismiss(); + accessibilityService.playSound(SoundEvent.V_CANCEL); + accessibilityService.speak(getHeaderText().toString()); + } + } + + }); + + return false; + } + + public String getName(){ + return "Select File to Save"; + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/activities/TreeNavigation.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,793 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.activities; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService; +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService.SoundEvent; +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibleCheckbox; +import uk.ac.qmul.eecs.ccmi.accessibility.AccessibleDialogBuilder; +import uk.ac.qmul.eecs.ccmi.utilities.Stack; +import uk.ac.qmul.eecs.ccmi.xmlparser.Diagram; +import uk.ac.qmul.eecs.ccmi.xmlparser.DiagramUpdater; +import uk.ac.qmul.eecs.ccmi.xmlparser.Edge; +import uk.ac.qmul.eecs.ccmi.xmlparser.EdgeNode; +import uk.ac.qmul.eecs.ccmi.xmlparser.EdgeType; +import uk.ac.qmul.eecs.ccmi.xmlparser.HierarchyItem; +import uk.ac.qmul.eecs.ccmi.xmlparser.LocalDiagramUpdater; +import uk.ac.qmul.eecs.ccmi.xmlparser.Modifier; +import uk.ac.qmul.eecs.ccmi.xmlparser.Node; +import uk.ac.qmul.eecs.ccmi.xmlparser.NodeProperty; +import uk.ac.qmul.eecs.ccmi.xmlparser.NodePropertyType; +import uk.ac.qmul.eecs.ccmi.xmlparser.NodeType; +import uk.ac.qmul.eecs.ccmi.xmlparser.PropertyValue; +import android.support.v4.app.DialogFragment; +import android.view.View; +import android.widget.AdapterView; +import android.widget.EditText; +import android.widget.Spinner; + +/** + * Provides a navigation of the model (the diagram) based on the tree hierarchy of the + * <a href="http://ccmi.eecs.qmul.ac.uk">CCmI Diagram Editor</a> + * + */ +class TreeNavigation { + + private static final String RENAME_DIALOG_TAG = "Rename "; + private static final String EDIT_NODE_DIALOG_TAG = "Edit Node Dialog"; + private static final String EDIT_EDGE_DIALOG_TAG = "Edit Edge Dialog"; + private static final String EDIT_NODE_REF_DIALOG_TAG = "Edit Node Reference Dialog"; + private static final String EDIT_LABEL_DIALOG_TAG = "Edit Label"; + private static final String EDIT_ARROWHEAD_DIALOG_TAG = "Edit Arrow Head Dialog"; + private static final String CONFIRMATION_DIALOG_TAG = "Are you sure you want to delete"; + private static final String ADD_PROPERTY_DIALOG_TAG = "Add Property Dialog"; + private static final String EDIT_PROPERTY_DIALOG_TAG = "Edit Property Dialog"; + private static final String EDIT_MODIFIERS_DIALOG_TAG = "Edit Modifiers Dialog"; + + private Diagram diagram; + private DiagramUpdater diagramUpdater; + private Stack<HierarchyItem> path; + + private List<Node> selectedNodes = new ArrayList<Node>(4); + /* cached list is filled up when next() and previous() and used to undo the navigation + * if the list created is empty. Once created, then it's returned by getCurrentList() */ + private String[] cachedList; + private Stack<String> cachedHeaderTexts; + + /* controller for edit actions with access to the current status of the navigation */ + private Controller controller; + private Updateable updateable; + + /* the level currently displayed. Level item's toString() is on the header * + * text and its children are displayed in the currentList */ + private final static int PATH_MAX_LEN = 5; + public final static int DIAGRAM_LEVEL = 0; + public final static int TYPE_LEVEL = 1; + public final static int ITEM_LEVEL = 2; + public final static int REFERENCE_AND_PROPERTY_TYPE_LEVEL = 3; + public final static int PROPERTY_AND_EDGE_REFERENCE_LEVEL = 4; // neved used + + public TreeNavigation(Diagram diagram, AccessibleDialogBuilder dialogBuilder, Updateable updateable){ + this.diagram = diagram; + this.updateable = updateable; + diagramUpdater = new LocalDiagramUpdater(diagram); + path = new Stack<HierarchyItem>(PATH_MAX_LEN); + cachedHeaderTexts = new Stack<String>(PATH_MAX_LEN); + /* tree path starts with top node */ + path.push(diagram); + cachedHeaderTexts.push(diagram.toString()); + cachedList = buildCurrentChildList(); + controller = new Controller(dialogBuilder); + } + + public String[] getCurrentChildList(){ + return cachedList; + } + + public String getCurrentPath(){ + StringBuilder builder = new StringBuilder(); + for(HierarchyItem item : path){ + builder.append('/').append(item); + } + return builder.toString(); + } + + /* builds the String list of items to display when getCurrentListIsCalled */ + private String[] buildCurrentChildList(){ + String[] currentList = null; + switch(path.level()){ + case DIAGRAM_LEVEL :{ + List<NodeType> nodeTypes = diagram.getPrototypes().getNodeTypes(); + List<EdgeType> edgeTypes = diagram.getPrototypes().getEdgeTypes(); + int numNodeTypes = nodeTypes.size(); + int numEdgeTypes = edgeTypes.size(); + currentList = new String[numNodeTypes+numEdgeTypes]; + + /* build the string for each node type */ + StringBuilder builder = new StringBuilder(); + for(int i=0; i<numNodeTypes;i++){ + builder.setLength(0); + builder.append(nodeTypes.get(i).getType()) + .append(' ') + .append('(') + .append(count(nodeTypes.get(i))) + .append(')'); + currentList[i] = builder.toString(); + } + /* build the string for each edge type */ + for(int j=0; j<numEdgeTypes; j++){ + builder.setLength(0); + builder.append(edgeTypes.get(j).getType()) + .append(' ') + .append('(') + .append(count(edgeTypes.get(j))) + .append(')'); + currentList[numNodeTypes+j] = builder.toString(); + } + + break; + } + case TYPE_LEVEL : { + /* list all objects of a certain type */ + LinkedList<String> items = new LinkedList<String>(); + if(path.current() instanceof NodeType){ + for(Node cNode : diagram.getComponents().getNodes()){ + if(path.current().toString().equals(cNode.getType())) + if(selectedNodes.contains(cNode)) + items.add("<"+cNode+">"); // <selected node> + else + items.add(cNode.getName()); + } + }else{ + for(Edge cEdge : diagram.getComponents().getEdges()){ + if(path.current().toString().equals(cEdge.getType())) + items.add(cEdge.getName()); + } + } + currentList = items.toArray(new String[items.size()]); + break; + } + case ITEM_LEVEL : { + Map<String,Integer> edgeTypes = new LinkedHashMap<String,Integer>(); + if(path.current() instanceof Node){ + /* node displays the list of edge types connected to * + * itself + the list of property types defined for itself */ + Node node = (Node)path.current(); + /* add the edge types of the edges the node is attached to */ + for(Edge cEdge : diagram.getComponents().getEdges()){ + for(EdgeNode attachedNode : cEdge.getAttachedNodes()){ + if(attachedNode.getId() == node.getId()){ + if(!edgeTypes.containsKey(cEdge.getType())){ + edgeTypes.put(cEdge.getType(),1); + }else{ + edgeTypes.put(cEdge.getType(),edgeTypes.get(cEdge.getType())+1); + } + break; + } + } + } + + /* build the array to return : first part is the edge types. second part property types / + /* now the property types this node can have */ + currentList = new String[edgeTypes.size()+node.getProperties().size()]; + int i = 0; + StringBuilder builder = new StringBuilder(); + for(Map.Entry<String, Integer> entry : edgeTypes.entrySet()){ + builder.setLength(0); + currentList[i++] = builder.append(entry.getKey()) + .append(' ') + .append('(') + .append(entry.getValue()) + .append(')').toString(); + } + + for(int j=i;j<currentList.length;j++){ + builder.setLength(0); + currentList[j] = builder.append(node.getProperties().get(j-i).getType()) + .append(' ') + .append('(') + .append(node.getProperties().get(j-i).getValues().size()) + .append(')').toString(); + } + + }else{ // Edge + /* edge displays the list of nodes attached to self */ + Edge cEdge = (Edge)path.current(); + currentList = new String[cEdge.getAttachedNodes().size()]; + int i = 0; + for(EdgeNode attachedNode : cEdge.getAttachedNodes()){ + for(Node node : diagram.getComponents().getNodes()){ + if(node.getId() == attachedNode.getId()){ + currentList[i++] = (attachedNode.getHead()+" "+node.getName()+" "+attachedNode.getLabel()).trim(); + } + } + } + } + break; + } + case REFERENCE_AND_PROPERTY_TYPE_LEVEL : { + /* display the values of the selected property types */ + if(path.current() instanceof NodeProperty){ // property type is displayed on the header + NodeProperty property = (NodeProperty)path.current(); + currentList = new String[property.getValues().size()]; + NodeType nodeType = (NodeType)path.get(TYPE_LEVEL); + + /* for each property value build the string "mod1 mod2 mod3...value" * + * where modn is the modifier type and value is the property value */ + StringBuilder builder = new StringBuilder(); + for(int i=0; i<currentList.length; i++){ + builder.setLength(0); + List<Integer> modifierIndexes = property.getValues().get(i).getModifiersIndexes(); + for(NodePropertyType propertyType : nodeType.getPropretyTypes()){ + if(propertyType.getType().equals(property.getType())){ + ArrayList<Modifier> modifiers = propertyType.getModifiers(); + for(Integer j : modifierIndexes){ + builder.append(modifiers.get(j).getType()).append(' '); + } + } + } + currentList[i] = builder.append(property.getValues().get(i).getValue()).toString(); + } + +// NodeProperty propertyType = (NodeProperty)path.current(); +// Node node = (Node)path.get(ITEM_LEVEL); +// for(NodeProperty property : node.getProperties()){ +// if(property.getType().equals(propertyType.getType())){ +// currentList = new String[property.getValues().size()]; +// for(int i=0; i<currentList.length; i++){ +// currentList[i] = property.getValues().get(i).getValue(); +// } +// break; +// } +// } + }else{ // instance of EdgeType + EdgeType edgeType = (EdgeType)path.current(); + LinkedList<String> currentListItems = new LinkedList<String>(); + int nodeID = ((Node)path.get(ITEM_LEVEL)).getId(); + StringBuilder builder = new StringBuilder(); + for(Edge edge : diagram.getComponents().getEdges()){ + if(edge.getType().equals(edgeType.getType())){ + for(EdgeNode attachedNode : edge.getAttachedNodes()){ + if(attachedNode.getId() == nodeID){ + currentListItems.add(makeEdgeReferenceString(edge,nodeID,builder)); + } + } + } + } + currentList = currentListItems.toArray(new String[currentListItems.size()]); + } + break; + } + default : new IllegalStateException("Wrong path level: "+path.level()); + } + return currentList; + } + + /** + * Returns the label of the parent of the list currently visualized + * + * @return the label of the parent + */ + public String getCurrentItemName(){ + String text = cachedHeaderTexts.current(); + if(text != null) + return text; + else + return path.current().toString(); + } + + /** + * Returns the level of the navigation at the moment the method is called. + * + * @return an {@code int} representing the current level. Possible values are + * listed as {@code static} variables of this class. + */ + public int getCurrentLevel(){ + return path.level(); + } + + /** + * Makes a child of the current {@code HierarchyItem} the current one. + * + * @param child the index of the child becoming the current + * @return {@code true} if the current position has changed after the call + **/ + public boolean goNext(int child){ + if(child < 0) + throw new IllegalArgumentException("Wrong child index: "+child); + + HierarchyItem hierarchyItem = findNext(child); + if(hierarchyItem == null) + return false; + + path.push(hierarchyItem); + /* saves the selected list item to display as a title on the next call to getCurrentHeaderText() */ + cachedHeaderTexts.push(cachedList[child]); + /* make the new list to return for next calls to getCurrentList() */ + cachedList = buildCurrentChildList(); + /* the selected hierarchy node has no children. go back and return false */ + if(cachedList.length == 0){ + goPrevious(); + return false; + } + updateable.update(); + return true; + } + + private HierarchyItem findNext(int child){ + switch(path.level()){ + case DIAGRAM_LEVEL :{ + List<NodeType> nodeTypes = diagram.getPrototypes().getNodeTypes(); + List<EdgeType> edgeTypes = diagram.getPrototypes().getEdgeTypes(); + int numNodeTypes = nodeTypes.size(); + int numEdgeTypes = edgeTypes.size(); + if(child >= numNodeTypes+numEdgeTypes) + throw new IllegalArgumentException("Wrong child index: "+child); + + if(child < numNodeTypes){ + return nodeTypes.get(child); + }else{ + return edgeTypes.get(child-numNodeTypes); + } + } + case TYPE_LEVEL : { + int numTypeItems = 0;// the number of nodes or edges found of the current type + if(path.current() instanceof NodeType){ + /* find the child-th node of the current type */ + for(Node node : diagram.getComponents().getNodes()){ + if(path.current().toString().equals(node.getType())){ + if(numTypeItems == child){ + return node; + }else{ + numTypeItems++; + } + } + } + }else{ // EdgeType + for(Edge edge : diagram.getComponents().getEdges()){ + /* find the child-th edge of the current type */ + if(path.current().toString().equals(edge.getType())){ + if(numTypeItems == child){ + return edge; + }else{ + numTypeItems++; + } + } + } + } + break; + } + case ITEM_LEVEL : { + /* we can go further only for nodes */ + if(path.current() instanceof Node){ + Node node = (Node)path.current(); + /* check if user clicked on an edge, this node is attached to */ + + Set<String> cNodeEdgeTypes = new LinkedHashSet<String>(); + /* for each edge component */ + for(Edge edge : diagram.getComponents().getEdges()){ + /* for each attached node to this edge */ + for(EdgeNode attachedNode : edge.getAttachedNodes()){ + /* if it's this node we're looking for (cNode) */ + if(attachedNode.getId() == node.getId()){ + cNodeEdgeTypes.add(edge.getType()); + } + } + } + + if(child < cNodeEdgeTypes.size()){ + String selectedType = cNodeEdgeTypes.toArray(new String[cNodeEdgeTypes.size()])[child]; + for(EdgeType edge : diagram.getPrototypes().getEdgeTypes()){ + if(edge.getType().equals(selectedType)){ + return edge; + } + } + }else{// user selected a NodePropertyType put a NodeProperty in the path + return node.getProperties().get(child-cNodeEdgeTypes.size()); + } + break; + } + } + default : return null; // don't go further than REFERENCE_AND_PROPERTY_LEVEL + } + return null; + } + + /** + * Makes the father of the current {@code HierarchyItem} the current one. + * @return @code true} if the current position has changed after the call + */ + public boolean goPrevious(){ + if(path.level() == DIAGRAM_LEVEL) // level = DIAGRAM_LEVEL + return false; + path.pop(); + cachedList = buildCurrentChildList(); + cachedHeaderTexts.pop(); + return true; + } + + /** + * Returns a controller, that can be used to + * change the model (the diagram) in a way coherent to the tree navigation + * + * @return a controller connected to this navigation + */ + public Controller getController(){ + return controller; + } + + /* Counts the number of nodes or edges of a given type */ + private int count(HierarchyItem hItem){ + int count = 0; + if(hItem instanceof NodeType){ + NodeType node = (NodeType)hItem; + for(Node cNode : diagram.getComponents().getNodes()) + if(cNode.getType().equals(node.getType())) + count++; + }else if(hItem instanceof EdgeType){ + EdgeType edge = (EdgeType)hItem; + for(Edge cEdge : diagram.getComponents().getEdges()) + if(cEdge.getType().equals(edge.getType())) + count++; + } + return count; + } + + /* Creates a string for the node reference of edge related to the node N equal to ID nodeID. + * The string looks like "to N1, N2 and N3 vie E", where N1, N2 and N3 are the nodes connected + * to N via E ( they can be more than one in case of a multiple ended edge ). + */ + private String makeEdgeReferenceString(Edge edge, int nodeID, StringBuilder builder) { + builder.setLength(0); + builder.append("to "); + /* attach the name of the nodes interleaved by " and " */ + for(int i=0; i<edge.getAttachedNodes().size(); i++){ + EdgeNode attachedNode = edge.getAttachedNodes().get(i); + if(attachedNode.getId() != nodeID){ + for(Node cNode : diagram.getComponents().getNodes()){ + if(cNode.getId() == attachedNode.getId()){ + if(i == edge.getAttachedNodes().size()-1){ + builder.append(cNode.getName()); + }else if(i == edge.getAttachedNodes().size()-2){ + builder.append(cNode.getName()).append(" and "); + }else{ + builder.append(cNode.getName()).append(", "); + } + break; + } + } + } + } + builder.append(", via "); + builder.append(edge.getName()); + return builder.toString(); + } + + /* A controller that changes the model (the data structures in the xml parser package) using the informations * + * given by the TreeNavigation. When commands are issued by the user (through long click) the controller pops * + * up a dialog according to what the user chose and which layer of the tree they are currently visualizing * + * if the user issues the command (doesn't cancel the dialog) the model is updated and the updater * + * is called to refresh and visualize the result */ + class Controller implements AccessibleDialogBuilder.ButtonClickListener { + AccessibleDialogBuilder dialogBuilder; + HierarchyItem clickedItem; + + Controller(AccessibleDialogBuilder dialogBuilder){ + this.dialogBuilder = dialogBuilder; + }; + + /* + * Responds to the long cick of the user. It acts according to the list item clicked + * by the user (and therefore according to the hierarchy level currently displayed). + * When a dialog needs to be shown, it used dialogBuilder.displayDialog() and register itself + * as buttoClickListener to handle the click of the user in the same class. + */ + public boolean performEditAction(AdapterView<?> parent, View view, + int position, long id, Updateable u) { + switch(getCurrentLevel()){ + case TreeNavigation.DIAGRAM_LEVEL : { + List<NodeType> nodeTypes = diagram.getPrototypes().getNodeTypes(); + if(position < nodeTypes.size()){ // user clicked on a node + clickedItem = nodeTypes.get(position); + /* build the properties for node constructor using node property types */ + NodeType nodeType = nodeTypes.get(position); + ArrayList<NodeProperty> properties = new ArrayList<NodeProperty>(nodeType.getPropretyTypes().size()); + for(NodePropertyType pType : nodeType.getPropretyTypes()){ + properties.add(new NodeProperty(pType.getType())); + } + /* construct the node and add it to the diagram */ + Node node = new Node(((NodeType)clickedItem).getType(),properties); + diagramUpdater.addNode(node); + dialogBuilder.getAccessibilityService().speak("Node "+ node +" created"); + }else{ // user clicked on edge + List<EdgeType> edgeTypes = diagram.getPrototypes().getEdgeTypes(); + clickedItem = edgeTypes.get(position - nodeTypes.size()); + /* respect min and max attached nodes */ + if(selectedNodes.size() < ((EdgeType)clickedItem).getMinAttachedNodes()){ + dialogBuilder.getAccessibilityService().speak("you must select at least "+ + ((EdgeType)clickedItem).getMinAttachedNodes()+" nodes"); + return true; + } + if(selectedNodes.size() > ((EdgeType)clickedItem).getMaxAttachedNodes()){ + dialogBuilder.getAccessibilityService().speak("you must select at most "+ + ((EdgeType)clickedItem).getMaxAttachedNodes()+" nodes"); + return true; + } + + /* create the edge and add the edge nodes */ + Edge edge = new Edge(((EdgeType)clickedItem).getType()); + edge.getAttachedNodes().clear(); + /* create all the node references (EdgeNode) for this edge */ + for(Node n : diagram.getComponents().getNodes()){ + if(selectedNodes.contains(n)) + edge.getAttachedNodes().add(new EdgeNode(n.getId())); + } + diagramUpdater.addEdge(edge); + StringBuilder builder = new StringBuilder(); + builder.append(edge).append(" created between "); + for(int i=0; i<selectedNodes.size(); i++){ + Node sn = selectedNodes.get(i); + builder.append(sn.getName()); + if(i == selectedNodes.size() - 2 ){ + builder.append(", and "); + }else if (i != selectedNodes.size() - 1 ){ + builder.append(", "); + } + } + selectedNodes.clear(); // when an edge is added the selected node are cleared + dialogBuilder.getAccessibilityService().speak(builder.toString()); + } + /* update the view */ + cachedList = buildCurrentChildList(); + updateable.update(); + return true; + } + case TreeNavigation.TYPE_LEVEL :{ + clickedItem = findNext(position); + /* path.current() is what's displayed on the header */ + if(path.current() instanceof NodeType){ // Node + if(selectedNodes.contains(clickedItem)){ + dialogBuilder.displayDialog(R.layout.alert_dialog_edit_node_unselect, EDIT_NODE_DIALOG_TAG, this); + }else{ + dialogBuilder.displayDialog(R.layout.alert_dialog_edit_node, EDIT_NODE_DIALOG_TAG, this); + } + }else{ // Edge + dialogBuilder.displayDialog(R.layout.alert_dialog_edit_edge, EDIT_EDGE_DIALOG_TAG, this); + } + return true; + } + case TreeNavigation.ITEM_LEVEL :{ + if(path.current() instanceof Node){ // Node + clickedItem = findNext(position); + /* edge types inside node cannot be edited directly */ + if(clickedItem instanceof EdgeType) + return false; + /* if it ain't an EdgeType then t's a PropertyType */ + /* property type items can be used to add new properties */ + dialogBuilder.displayDialog(R.layout.alert_dialog_add_property, ADD_PROPERTY_DIALOG_TAG, this); + }else{ // Edge + clickedItem = ((Edge)path.current()).getAttachedNodes().get(position); + dialogBuilder.displayDialog(R.layout.alert_dialog_edit_node_reference, EDIT_NODE_REF_DIALOG_TAG, this); + } + return true; + } + case TreeNavigation.REFERENCE_AND_PROPERTY_TYPE_LEVEL :{ + if(path.current() instanceof NodeProperty){ + NodeProperty nodeProperty = (NodeProperty)path.current(); + clickedItem = nodeProperty.getValues().get(position); + dialogBuilder.displayDialog(R.layout.alert_dialog_edit_property, EDIT_PROPERTY_DIALOG_TAG, this); + return true; + } + return false; + } + case TreeNavigation.PROPERTY_AND_EDGE_REFERENCE_LEVEL :{ + return false;// never happens + } + } + return false; + } + + /* this is the callback triggered when the user clicks on any bottom of the dialog shown. v is the button + * The method first checks for the dialog tag to understand which dialog it's handling, then it checks + * for the button tag to understand which button the user pressed. The first check though is on "CANCEL" + * button as its tag it's the same for all the dialog */ + @Override + public void onClick(View v, DialogFragment dialogFragment, String dialogTag) { + Object buttonTag = v.getTag(); + AccessibilityService accessibility = dialogBuilder.getAccessibilityService(); + + if("CANCEL".equals(buttonTag)){ + accessibility.speak("Cancel"); + dialogFragment.dismiss(); + return; + } + + if(EDIT_NODE_DIALOG_TAG.equals(dialogTag) || EDIT_EDGE_DIALOG_TAG.equals(dialogTag)){ + if("SELECT".equals(buttonTag)){ + selectedNodes.add((Node)clickedItem); + accessibility.playSound(SoundEvent.V_OK); + accessibility.speak(clickedItem + " selected"); + }else if("UNSELECT".equals(buttonTag)){ + selectedNodes.remove(clickedItem); + accessibility.playSound(SoundEvent.V_OK); + accessibility.speak(clickedItem + " unselected"); + }else if("RENAME".equals(buttonTag)){ + dialogFragment.dismiss(); + dialogBuilder.displayDialog(R.layout.alert_dialog_rename, RENAME_DIALOG_TAG+clickedItem, this); + }else if("DELETE".equals(buttonTag)){ + dialogFragment.dismiss(); + dialogBuilder.displayDialog(R.layout.alert_dialog_confirmation, + CONFIRMATION_DIALOG_TAG+ + (EDIT_NODE_DIALOG_TAG.equals(dialogTag) ? " Node " : " Edge ") + + clickedItem, + this); + } + }else if(dialogTag.startsWith(RENAME_DIALOG_TAG)){ + /* if it reached this point it'a "RENAME" button as "CANCEL" * + * have been matched against at the beginning of the method */ + EditText editText = (EditText)dialogFragment.getDialog().findViewById(R.id.text_edit); + String text = editText.getText().toString().trim(); + if(text.length() == 0){ + accessibility.playSound(SoundEvent.V_ERROR); + accessibility.speak("Text cannot be empty"); + return; + } + String oldName = clickedItem.toString(); + diagramUpdater.rename(clickedItem,text); + accessibility.playSound(SoundEvent.V_OK); + accessibility.speak(oldName+" renamed to "+clickedItem); + }else if(dialogTag.startsWith(CONFIRMATION_DIALOG_TAG)){ + /* if it reaches this point it's a "YES" as a "NO" button has "CANCEL" as its tag */ + /* and the match against "CANCEL" match is performed first of all */ + diagramUpdater.delete(clickedItem); + /* if it's a selected node, remove it from selected */ + selectedNodes.remove(clickedItem); + accessibility.speak(clickedItem+" Deleted"); + /* update the headers which show the number of children the current item contains */ + if(path.current() instanceof NodeType || path.current() instanceof EdgeType){ + cachedHeaderTexts.pop(); + cachedHeaderTexts.push(path.current()+" ("+count(path.current())+')'); + }else if(path.current() instanceof NodeProperty){ + cachedHeaderTexts.pop(); + cachedHeaderTexts.push(path.current()+" ("+((NodeProperty)path.current()).getValues().size()+')'); + } + }else if(ADD_PROPERTY_DIALOG_TAG.equals(dialogTag)){ + /* if it reaches this point it's a "CREATE" as "CANCEL" would * + * have been matched against at the beginning of the method */ + EditText editText = (EditText)dialogFragment.getDialog().findViewById(R.id.text_edit); + String text = editText.getText().toString().trim(); + if(text.length() == 0){ + accessibility.playSound(SoundEvent.V_ERROR); + accessibility.speak("Text cannot be empty"); + return; + } + diagramUpdater.addProperty((Node)path.get(ITEM_LEVEL),((NodeProperty)clickedItem),text); + accessibility.playSound(SoundEvent.V_OK); + accessibility.speak("Property "+text+" added"); + }else if(EDIT_NODE_REF_DIALOG_TAG.equals(dialogTag)){ + if("EDIT_LABEL".equals(buttonTag)){ + dialogFragment.dismiss(); + dialogBuilder.displayDialog(R.layout.alert_dialog_rename, EDIT_LABEL_DIALOG_TAG, this); + }else{ // EDIT_ARROWHEAD + dialogFragment.dismiss(); + Edge edge = (Edge)path.current(); // get the edge this node reference belongs to + String[] heads = null; + /* build a string array with all the available head labels for this edge's type */ + for(EdgeType edgeType : diagram.getPrototypes().getEdgeTypes()){ + if(edgeType.getType().equals(edge.getType())){ + heads = new String[edgeType.getHeads().size()]; + for(int i=0; i<heads.length;i++) + heads[i] = edgeType.getHeads().get(i).getHeadLabel(); + break; + } + } + if(heads == null || heads.length == 0){ + accessibility.playSound(SoundEvent.V_ERROR); + accessibility.speak("There are no arrow heads defined for "+edge); + return; + } + dialogBuilder.displaySelectionDialog(EDIT_ARROWHEAD_DIALOG_TAG, heads, this); + } + }else if(EDIT_LABEL_DIALOG_TAG.equals(dialogTag)){ + EditText editText = (EditText)dialogFragment.getDialog().findViewById(R.id.text_edit); + String text = editText.getText().toString().trim(); + if(text.length() == 0){ + accessibility.playSound(SoundEvent.V_ERROR); + accessibility.speak("Text cannot be empty"); + return; + } + diagramUpdater.setLabel((EdgeNode)clickedItem,text); + accessibility.playSound(SoundEvent.V_OK); + accessibility.speak("Label set to "+clickedItem);// EdgeNode.toString = EdgeNode.getLabel + }else if(EDIT_ARROWHEAD_DIALOG_TAG.equals(dialogTag)){ + Spinner spinner = (Spinner)dialogFragment.getDialog().findViewById(R.id.selectionSpinner); + ((EdgeNode)clickedItem).setHead(spinner.getSelectedItem().toString()); + accessibility.playSound(SoundEvent.V_OK); + accessibility.speak("Arrow head set to "+spinner.getSelectedItem().toString()); + }else if(EDIT_PROPERTY_DIALOG_TAG.equals(dialogTag)){ + if("RENAME".equals(buttonTag)){ + dialogFragment.dismiss(); + dialogBuilder.displayDialog(R.layout.alert_dialog_rename, RENAME_DIALOG_TAG, this); + }else if("DELETE".equals(buttonTag)){ + dialogFragment.dismiss(); + dialogBuilder.displayDialog(R.layout.alert_dialog_confirmation, + CONFIRMATION_DIALOG_TAG+ " property "+clickedItem, + this); + }else if("MODIFIERS".equals(buttonTag)){ + dialogFragment.dismiss(); + /* get the modifiers from the NodePropertyType of the node where this property is */ + NodeProperty property = (NodeProperty)path.current(); + String[] modifiers = null; + boolean[] checks = null; + for( NodePropertyType propertyType : ((NodeType)path.get(TYPE_LEVEL)).getPropretyTypes()){ + if(propertyType.getType().equals(property.getType())){ + modifiers = new String[propertyType.getModifiers().size()]; + checks = new boolean[modifiers.length]; + for(int i=0; i< modifiers.length; i++){ + modifiers[i] = propertyType.getModifiers().get(i).getType(); + if(((PropertyValue)clickedItem).getModifiersIndexes().contains(i)) + checks[i] = true; + } + } + } + if(modifiers == null || modifiers.length == 0){ + accessibility.playSound(SoundEvent.V_ERROR); + accessibility.speak("There are no modifiers defined for "+property); + return; + } + dialogBuilder.displayCheckDialog(EDIT_MODIFIERS_DIALOG_TAG, modifiers, checks, this); + } + }else if(EDIT_MODIFIERS_DIALOG_TAG.equals(dialogTag)){ + /* pressed button is OK as CANCEL would have been cought at the beginning */ + AccessibleCheckbox checkbox = (AccessibleCheckbox)dialogFragment.getDialog().findViewById(R.id.checkBox); + boolean[] checks = checkbox.getChecks(); + List<Integer> modifiers = new ArrayList<Integer>(checks.length); + for(int i=0; i<checks.length; i++){ + if(checks[i]) + modifiers.add(i); + } + diagramUpdater.setModifiers((PropertyValue)clickedItem, modifiers); + } + /* update the view */ + cachedList = buildCurrentChildList(); + updateable.update(); + dialogFragment.dismiss(); + } + } + + /** + * + * Simple interface to provide an update method + * + */ + interface Updateable { + /** + * performs an update + */ + public void update(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/utilities/Stack.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,93 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.utilities; + +import java.util.ArrayList; + +/** + * + * The stack is an {@code ArrayList} with a simplified interface for pushing and popping elements + * on and from the top + * + * @param <T> The type of objects contained in this stack + */ +public class Stack<T> extends ArrayList<T> { + + /** + * Create a stack with an initial capacity of {@code size} + * + * @param size the initial capacity + */ + public Stack(int size){ + super(size); + } + + /** + * Returns the size of the stack + * + * @return the size of the stack + */ + @Override + public int size(){ + return super.size(); + } + + /** + * Return the index of the top element for the stack + * + * @return index of the top element for the stack or -1 if the stack is empty + */ + public int level(){ + return size()-1; + } + + /** + * Adds a new element at the top of the stack. Like in an {@code ArrayList}, + * the same object can be inserted more than once in the stack + * + * @param n the new element to add + */ + public void push(T n){ + add(n); + } + + /** + * Removes the top element of the stack + * + * @return the removed element or {@code null} if the stack is empty + */ + public T pop(){ + if(size() == 0) + return null; + return remove(size()-1); + } + + /** + * Returns a reference to the top element of the stack, the element is not removed + * + * @return the top element of the stack + */ + public T current(){ + if(size() == 0) + return null; + return get(size()-1); + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/Components.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,57 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import java.util.ArrayList; +import java.util.List; + +import org.simpleframework.xml.ElementList; +import org.simpleframework.xml.Root; + +@Root(name="Components") +public class Components{ + @ElementList(name="Nodes") + private List<Node> nodes; + + @ElementList(name="Edges") + private List<Edge> edges; + + + public List<Node> getNodes() { + return nodes; + } + + public void setNodes(List<Node> nodes) { + this.nodes = nodes; + } + + public List<Edge> getEdges() { + return edges; + } + + public void setEdges(List<Edge> edges) { + this.edges = edges; + } + + public Components(){ + nodes = new ArrayList<Node>(); + edges = new ArrayList<Edge>(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/Diagram.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,88 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import org.simpleframework.xml.Attribute; +import org.simpleframework.xml.Element; +import org.simpleframework.xml.Root; + + +@Root(name="Diagram") +public class Diagram implements HierarchyItem { + + @Attribute(name="Name") + private String name; + + @Attribute(name="PrototypeDelegate") + private String prototypeDelegate; + + @Element(name="Prototypes") + private Prototypes prototype; + + @Element(name="Components") + private Components components; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPrototypeDelegate() { + return prototypeDelegate; + } + + public void setPrototypeDelegate(String prototypeDelegate) { + this.prototypeDelegate = prototypeDelegate; + } + + public Prototypes getPrototypes() { + return prototype; + } + + public void setPrototypes(Prototypes prototype) { + this.prototype = prototype; + } + + public Components getComponents() { + return components; + } + + public void setComponents(Components components) { + this.components = components; + } + + public Diagram(){ + super(); + } + + public Diagram(String name){ + this.name = name; + prototype = new Prototypes(); + components = new Components(); + } + + @Override + public String toString() { + return name; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/DiagramUpdater.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,51 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import java.util.List; + +/** + * + * This interface must be implemented by classes who implement a strategy for changing the diagram model. + * Doing this through an interface allows interchangeability of strategies. + * This comes handy for eventual further implementations of a network-based real time sharing system. So + * the network client can implement this interface and, instead of directly changing the diagram, it can send + * messages to a server and change it accordingly to the server reply. + * All in a transparent way to the classes which are in charge of editing the diagram. + * + */ +public interface DiagramUpdater { + + public void addNode(Node node); + + public void addEdge(Edge edge); + + public void addProperty(Node node, NodeProperty nodeProperty, String proertyValue); + + public void rename(HierarchyItem item, String newName); + + public void delete(HierarchyItem item); + + public void setLabel(EdgeNode node, String label); + + public void setArrowHead(EdgeNode node, String arrowHead); + + public void setModifiers(PropertyValue propertyValue, List<Integer> modifiers); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/Edge.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,90 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + + +import java.util.ArrayList; + +import org.simpleframework.xml.Attribute; +import org.simpleframework.xml.ElementList; +import org.simpleframework.xml.Root; + +@Root(name="Edge",strict=false) +public class Edge implements HierarchyItem { + private static int idCounter = 0; + @Attribute(name="Name") + private String name; + @Attribute(name="Type") + private String type; + @Attribute(name="id") + private int id; + + private Edge(){ + id = ++idCounter; + name = "New Edge "+id; + } + + public Edge(String type){ + this(); + this.type = type; + name = "New "+type+" "+id; + } + + + @ElementList(name="Nodes") + private ArrayList<EdgeNode> attachedNodes=new ArrayList<EdgeNode>(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public int getId() { + return id; + } + + public void setId(int id) { + /* catch up with the highest value entered */ + if(id > idCounter){ + idCounter = id; + } + this.id = id; + } + + public ArrayList<EdgeNode> getAttachedNodes() { + return attachedNodes; + } + + public void setAttachedNodes(ArrayList<EdgeNode> cEPro) { + this.attachedNodes = cEPro; + } + + @Override + public String toString(){ + return name; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/EdgeNode.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,68 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import org.simpleframework.xml.Attribute; +import org.simpleframework.xml.Root; + +@Root(name="Node") +public class EdgeNode implements HierarchyItem{ + @Attribute(name="Head",required=false) + private String head; + + @Attribute(name="Label") + private String label; + + @Attribute(name="id") + private int id; + + public EdgeNode(){ + label = ""; + head = ""; + } + + public EdgeNode(int id){ + this(); + this.id = id; + } + + public String getHead() { + return head; + } + public void setHead(String head) { + this.head = head; + } + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } + public int getId() { + return id; + } + public void setId(int id) { + this.id = id; + } + + @Override + public String toString(){ + return label; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/EdgeType.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,84 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + + +import java.util.ArrayList; +import java.util.List; + +import org.simpleframework.xml.Element; +import org.simpleframework.xml.ElementList; +import org.simpleframework.xml.Root; + +@Root(name="Edge", strict=false) +public class EdgeType implements HierarchyItem { + + @Element(name="Type") + private String type; + + @Element(name="MinAttachedNodes") + private int minAttachedNodes; + + @Element(name="MaxAttachedNodes") + private int maxAttachedNodes; + + @ElementList(name="Heads",required=false) + private List<Head> heads; + + public EdgeType(){ + heads = new ArrayList<Head>(); + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getMinAttachedNodes() { + return minAttachedNodes; + } + + public void setMinAttachedNodes(int minAttachedNodes) { + this.minAttachedNodes = minAttachedNodes; + } + + public int getMaxAttachedNodes() { + return maxAttachedNodes; + } + + public void setMaxAttachedNodes(int maxAttachedNodes) { + this.maxAttachedNodes = maxAttachedNodes; + } + + public List<Head> getHeads() { + return heads; + } + + public void setHeads(ArrayList<Head> heads) { + this.heads = heads; + } + + @Override + public String toString(){ + return type; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/Head.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,49 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import org.simpleframework.xml.Attribute; +import org.simpleframework.xml.Root; + +@Root(name="Head") +public class Head { + + @Attribute(name="Head") + private String head; + @Attribute(name="headLabel") + private String headLabel; + public String getHead() { + return head; + } + public void setHead(String head) { + this.head = head; + } + public String getHeadLabel() { + return headLabel; + } + public void setHeadLabel(String headLabel) { + this.headLabel = headLabel; + } + + @Override + public String toString(){ + return getHeadLabel(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/HierarchyItem.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,33 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +/** + * + * Interface implemented by the classes of this package that are represent + * elements showed in the hierarchical view, when the user explores the diagram + * + */ +public interface HierarchyItem { + + /** + * {@code toString()} must be overwritten in order to return the label of the item + */ + public String toString(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/LocalDiagramUpdater.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,118 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import java.util.Iterator; +import java.util.List; + +/** + * An implementation of {@code DiagramUpdater} that immediately execute the commands on the local instance + * of {@code Diagram}. + */ +public class LocalDiagramUpdater implements DiagramUpdater { + Diagram diagram; + + /** + * Constructor + * + * @param diagram the diagram the commands will be executed on + */ + public LocalDiagramUpdater(Diagram diagram){ + this.diagram = diagram; + } + + @Override + public void addNode(Node node){ + diagram.getComponents().getNodes().add(node); + } + + @Override + public void rename(HierarchyItem item, String newName) { + if(item instanceof Node){ + ((Node)item).setName(newName); + }else if(item instanceof Edge){ + ((Edge)item).setName(newName); + }else if(item instanceof PropertyValue){ + ((PropertyValue)item).setValue(newName); + } + } + + @Override + public void delete(HierarchyItem item) { + if(item instanceof Node){ + diagram.getComponents().getNodes().remove(item); + Node node = (Node)item; + Iterator<Edge> iterator = diagram.getComponents().getEdges().iterator(); + /* we are deleting this node, so we need to remove it from * + * attached nodes list of the edges it's attached to */ + while(iterator.hasNext()){ + Edge edge = iterator.next(); + boolean removed = false; + for(EdgeNode edgeNode : edge.getAttachedNodes()){ + if(edgeNode.getId() == node.getId()){ + edge.getAttachedNodes().remove(edgeNode); + removed = true; + break; + } + } + /* there cannot be an edge with one node only. If the edge had two nodes one * + * of which was the deleted one, then the edge itself must be deleted */ + if(removed && edge.getAttachedNodes().size() == 1) + iterator.remove(); + } + + }else if(item instanceof Edge){ + diagram.getComponents().getEdges().remove(item); + }else if(item instanceof PropertyValue){ + for(Node node: diagram.getComponents().getNodes()){ + for(NodeProperty property : node.getProperties()){ + if(property.getValues().remove(item)){ + return; + } + } + } + } + } + + @Override + public void addEdge(Edge edge) { + diagram.getComponents().getEdges().add(edge); + } + + @Override + public void addProperty(Node node, NodeProperty property, String propertyValue) { + property.getValues().add(new PropertyValue(propertyValue)); + } + + @Override + public void setLabel(EdgeNode edgeNode, String label) { + edgeNode.setLabel(label); + } + + @Override + public void setArrowHead(EdgeNode edgeNode, String arrowHead) { + edgeNode.setHead(arrowHead); + } + + @Override + public void setModifiers(PropertyValue propertyValue, List<Integer> modifiers) { + propertyValue.setModifiersIndexes(modifiers); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/Modifier.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,77 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simpleframework.xml.Attribute; +import org.simpleframework.xml.Element; +import org.simpleframework.xml.Root; + +@Root(name="Modifier", strict=false) +public class Modifier{ + @Element(name="Type") + private String type; + + @Attribute(name="id") + private int id; + + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + + public int getId() { + return id; + } + public void setId(int id) { + this.id = id; + } + + + public static class ModifierList extends ArrayList<Modifier> { + + private static final long serialVersionUID = -5908877610880770292L; + + public ModifierList() { + super(); + } + + public ModifierList(Collection<? extends Modifier> collection) { + super(collection); + } + + public ModifierList(int capacity) { + super(capacity); + } + + @Override + public Modifier get(int id){ + for(Modifier modifier : this){ + if(modifier.id == id){ + return modifier; + } + } + throw new IndexOutOfBoundsException("No modifier with id:"+id); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/Node.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,89 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import java.util.ArrayList; + +import org.simpleframework.xml.Attribute; +import org.simpleframework.xml.ElementList; +import org.simpleframework.xml.Root; + +@Root(name="Node",strict=false) +public class Node implements HierarchyItem { + private static int idCounter = 0; + + @Attribute(name="Name") + private String name; + @Attribute(name="Type") + private String type; + @Attribute(name="id") + private int id; + + public Node(){ + id = ++idCounter; + name = "New Node "+id; + } + + public Node(String type, ArrayList<NodeProperty> properties){ + this(); + this.type = type; + name = "New "+type+" "+id; + this.properties = properties; + } + + @ElementList(name="Properties",required=false) + private ArrayList<NodeProperty> properties = new ArrayList<NodeProperty>(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public int getId() { + return id; + } + + public void setId(int id) { + /* catch up with the highest value entered */ + if(id > idCounter){ + idCounter = id; + } + this.id = id; + } + + public ArrayList<NodeProperty> getProperties() { + return properties; + } + + public void setProperties(ArrayList<NodeProperty> properties) { + this.properties = properties; + } + + @Override + public String toString(){ + return name; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/NodeProperty.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,60 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import java.util.ArrayList; + +import org.simpleframework.xml.Element; +import org.simpleframework.xml.ElementList; +import org.simpleframework.xml.Root; + + +@Root(name="Property") +public class NodeProperty implements HierarchyItem{ + + @Element(name="Type") + private String type; + + + @ElementList(name="Element",inline=true, required=false) + private ArrayList<uk.ac.qmul.eecs.ccmi.xmlparser.PropertyValue> values; + + public NodeProperty(){ + values = new ArrayList<uk.ac.qmul.eecs.ccmi.xmlparser.PropertyValue>(); + } + + public NodeProperty(String type){ + this(); + this.type = type; + } + + public ArrayList<uk.ac.qmul.eecs.ccmi.xmlparser.PropertyValue> getValues() { + return values; + } + + public String getType() { + return type; + } + + @Override + public String toString(){ + return type; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/NodePropertyType.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,48 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + + +import java.util.ArrayList; + +import org.simpleframework.xml.Element; +import org.simpleframework.xml.ElementList; +import org.simpleframework.xml.Root; + +@Root(name="Property", strict=false) +public class NodePropertyType { + @Element(name="Type") + private String type; + + @ElementList(name="Modifiers",required=false) + private ArrayList<Modifier> modifiers = new Modifier.ModifierList(5); + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public ArrayList<Modifier> getModifiers() { + return modifiers; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/NodeType.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,66 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + + +import java.util.ArrayList; + +import org.simpleframework.xml.Element; +import org.simpleframework.xml.ElementList; +import org.simpleframework.xml.Root; + +@Root(name="Node") +public class NodeType implements HierarchyItem { + + @Element(name="Type",required=false) + private String type; + @Element(name="ShapeType") + private String shapeType; + @ElementList(name="Properties") + private ArrayList<NodePropertyType> nodePropreties; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getShapeType() { + return shapeType; + } + + public void setShapeType(String shapeType) { + this.shapeType = shapeType; + } + + public ArrayList<NodePropertyType> getPropretyTypes() { + return nodePropreties; + } + + public void setNodePropreties(ArrayList<NodePropertyType> nodePropreties) { + this.nodePropreties = nodePropreties; + } + + @Override + public String toString(){ + return type; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/PropertyValue.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,63 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import java.util.ArrayList; +import java.util.List; + +import org.simpleframework.xml.Root; + + +@Root(name="Element") +public class PropertyValue implements HierarchyItem { + + @org.simpleframework.xml.Element(name="Value") + private String value; + @org.simpleframework.xml.ElementList(name="Modifiers",required=false) + private ArrayList<Integer> modifiers = new ArrayList<Integer>(); + + private PropertyValue(){} + + public PropertyValue(String value){ + this(); + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public List<Integer> getModifiersIndexes(){ + return modifiers; + } + + public void setModifiersIndexes(List<Integer> modifiers){ + this.modifiers.clear(); + this.modifiers.addAll(modifiers); + } + + @Override + public String toString(){ + return getValue(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/Prototypes.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,55 @@ +/* + CCmI Diagram Editor for Android + + Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package uk.ac.qmul.eecs.ccmi.xmlparser; + +import java.util.ArrayList; + +import org.simpleframework.xml.ElementList; +import org.simpleframework.xml.Root; + +@Root(name="Prototypes") +public class Prototypes{ + + @ElementList(inline=true,required=false) + private ArrayList<NodeType> nodeTypes; + + @ElementList(inline=true,required=false) + private ArrayList<EdgeType> edgeTypes; + + public Prototypes(){ + nodeTypes = new ArrayList<NodeType>(); + edgeTypes = new ArrayList<EdgeType>(); + } + + public ArrayList<NodeType> getNodeTypes() { + return nodeTypes; + } + + public void setNodeTypes(ArrayList<NodeType> node) { + this.nodeTypes = node; + } + + public ArrayList<EdgeType> getEdgeTypes() { + return edgeTypes; + } + + public void setEdgeTypes(ArrayList<EdgeType> edge) { + this.edgeTypes = edge; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/ccmi/xmlparser/package-info.java Thu Dec 13 20:00:21 2012 +0000 @@ -0,0 +1,18 @@ + + +/** + * + * Provides the classes necessary to parse the xml file, the + * <a href="http://ccmi.eecs.qmul.ac.uk" > CCmI Diagram Editor</a> uses to persist diagrams. + * + * The diagram is parsed and rendered as a structure of classes using the simpleframewors library. + * All the classes in this package, except {@code LocalDiagramUpdater} represent a part of the xml file. + * + * + * @see org.simpleframework + * + */ + + + +package uk.ac.qmul.eecs.ccmi.xmlparser; \ No newline at end of file