--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
--- /dev/null
+# Built application files
+*.apk
+*.ap_
+
+# Files for the Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+libs/
+obj/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>shape4a</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
+eclipse.preferences.version=1
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n *\tThis file is part of shape4a.\n *\n * shape4a is free software\: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * shape4a is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shape4a. If not, see <http\://www.gnu.org/licenses/>.\n *\n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * @author ${user}\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.ocera.orte.shape4a"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="8"
+ android:targetSdkVersion="15" />
+
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.WAKE_LOCK"/>
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name"
+ android:configChanges="screenSize|orientation" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) 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
+this service 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 make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. 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.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE 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.
+
+ 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
+convey 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 2 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, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision 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, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This 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.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="shape4a" default="help">
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The ant.properties file can be created by you. It is only edited by the
+ 'android' tool to add properties to it.
+ This is the place to change some Ant specific build properties.
+ Here are some properties you may want to change/update:
+
+ source.dir
+ The name of the source directory. Default is 'src'.
+ out.dir
+ The name of the output directory. Default is 'bin'.
+
+ For other overridable properties, look at the beginning of the rules
+ files in the SDK, at tools/ant/build.xml
+
+ Properties related to the SDK location or the project target should
+ be updated using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems.
+
+ -->
+ <property file="ant.properties" />
+
+ <!-- if sdk.dir was not set from one of the property file, then
+ get it from the ANDROID_HOME env var.
+ This must be done before we load project.properties since
+ the proguard config can use sdk.dir -->
+ <property environment="env" />
+ <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+ <isset property="env.ANDROID_HOME" />
+ </condition>
+
+ <!-- The project.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+
+ This contains project specific properties such as project target, and library
+ dependencies. Lower level build properties are stored in ant.properties
+ (or in .classpath for Eclipse projects).
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <loadproperties srcFile="project.properties" />
+
+ <!-- quick check on sdk.dir -->
+ <fail
+ message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+ unless="sdk.dir"
+ />
+
+ <!--
+ Import per project custom build rules if present at the root of the project.
+ This is the place to put custom intermediary targets such as:
+ -pre-build
+ -pre-compile
+ -post-compile (This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir})
+ -post-package
+ -post-build
+ -pre-clean
+ -->
+ <import file="custom_rules.xml" optional="true" />
+
+ <!-- Import the actual build file.
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <import> task.
+ - customize it to your needs.
+ - Customize the whole content of build.xml
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, replacing the <import> task.
+ - customize to your needs.
+
+ ***********************
+ ****** IMPORTANT ******
+ ***********************
+ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+ in order to avoid having your file be overridden by tools such as "android update project"
+ -->
+ <!-- version-tag: 1 -->
+ <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+</lint>
\ No newline at end of file
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# 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-15
+android.library.reference.1=../../../../../workspace/appcompat_v7
+android.library.reference.2=../../libaorte
--- /dev/null
+<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="org.ocera.orte.shape4a.MainActivity" />
--- /dev/null
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="org.ocera.orte.shape4a.MainActivity$PlaceholderFragment" >
+
+ <TextView
+ android:id="@+id/section_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</RelativeLayout>
--- /dev/null
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="org.ocera.orte.shape4a.MainActivity$PublisherFragment" >
+
+ <org.ocera.orte.shape4a.PublisherView
+ android:id="@+id/publisher_view"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+
+</RelativeLayout>
--- /dev/null
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="org.ocera.orte.shape4a.MainActivity$SubscriberFragment" >
+
+ <org.ocera.orte.shape4a.SubscriberView
+ android:id="@+id/subscriber_view"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+
+</RelativeLayout>
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="org.ocera.orte.shape4a.MainActivity" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:title="@string/action_settings"
+ app:showAsAction="never" />
+
+ <item
+ android:id="@+id/action_help"
+ android:orderInCategory="101"
+ android:title="@string/action_help"
+ app:showAsAction="never" />
+
+
+</menu>
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="org.ocera.orte.shape4a.MainActivity" >
+
+ <item
+ android:id="@+id/action_new"
+ android:orderInCategory="10"
+ android:title="@string/action_new"
+ android:icon="@drawable/ic_action_new"
+ app:showAsAction="ifRoom" />
+
+
+</menu>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="org.ocera.orte.shape4a.MainActivity" >
+
+ <item android:id="@+id/action_blue"
+ android:title="@string/action_blue"
+ app:showAsAction="never" />
+
+ <item android:id="@+id/action_green"
+ android:title="@string/action_green"
+ app:showAsAction="never" />
+
+ <item android:id="@+id/action_red"
+ android:title="@string/action_red"
+ app:showAsAction="never" />
+
+ <item android:id="@+id/action_black"
+ android:title="@string/action_black"
+ app:showAsAction="never" />
+
+ <item android:id="@+id/action_yellow"
+ android:title="@string/action_yellow"
+ app:showAsAction="never" />
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">shape4a</string>
+ <string name="dialog_OK">OK</string>
+ <string name="dialog_cancel">Cancel</string>
+ <string name="dialog_newPublisher">Color for new Publisher?</string>
+ <string name="dialog_publisherSettings">Publisher #</string>
+ <string name="dialog_delete">Delete</string>
+ <string name="dialog_add">Add</string>
+ <string name="action_settings">Settings</string>
+ <string name="action_help">Help</string>
+ <string name="action_blue">Blue</string>
+ <string name="action_green">Green</string>
+ <string name="action_red">Red</string>
+ <string name="action_black">Black</string>
+ <string name="action_yellow">Yellow</string>
+ <string name="action_new">New</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+/**
+ *
+ * This file is part of shape4a.
+ *
+ * shape4a 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.
+ *
+ * shape4a 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 shape4a. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.ocera.orte.shape4a;
+
+import org.ocera.orte.*;
+import org.ocera.orte.types.*;
+
+import android.util.Log;
+
+/**
+ * Object to be send throw ORTE.
+ *
+ * @author jiri hubacek <jiri.hubacek@gmail.com>
+ * @version %I%, %G%
+ * @since 1.0
+ */
+public class Box extends MessageData
+{
+ private static final double DESTINATION_WIDTH = 389.0;
+ private static final double DESTINATION_HEIGHT = 256.0;
+
+ public boolean allowScaling;
+ public int color;
+ // is more shape than strength,
+ // strength is solved throw
+ // publisherProperties or
+ // throw subscriberProperties...
+ public int strength;
+ public BoxRect rectangle;
+
+ private double scaleWidth;
+ private double scaleHeight;
+
+ /**
+ * Add topic of new object.
+ *
+ * @param appDomain
+ * @param newTopic
+ * @since 1.0
+ */
+ public Box(DomainApp appDomain, String newTopic) {
+ super();
+ this.setTopic(newTopic);
+
+ if (!appDomain.regNewDataType("Box", this.getMaxDataLength())) {
+ Log.e("Box", "Cannot register data type 'Box'.");
+ }
+
+ this.rectangle = new BoxRect();
+ this.allowScaling = true;
+ this.scaleWidth = 1;
+ this.scaleHeight = 1;
+ }
+
+ /**
+ * Read data from buffer.
+ * @since 1.0
+ */
+ @Override
+ public void read() {
+ buffer.rewind();
+ if (this.allowScaling) {
+ this.rectangle.top_left_x = (short) (buffer.getShort() / this.scaleWidth);
+ this.rectangle.top_left_y = (short) (buffer.getShort() / this.scaleHeight);
+ this.rectangle.bottom_right_x = (short) (buffer.getShort() / this.scaleWidth);
+ this.rectangle.bottom_right_y = (short) (buffer.getShort() / this.scaleHeight);
+ } else {
+ this.rectangle.top_left_x = buffer.getShort();
+ this.rectangle.top_left_y = buffer.getShort();
+ this.rectangle.bottom_right_x = buffer.getShort();
+ this.rectangle.bottom_right_y = buffer.getShort();
+ }
+
+ this.strength = (int) buffer.getShort();
+ }
+
+ /**
+ * Write data to buffer.
+ * @since 1.0
+ */
+ @Override
+ public void write() {
+ buffer.rewind();
+ if (this.allowScaling) {
+ buffer.putShort((short) (rectangle.top_left_x * this.scaleWidth));
+ buffer.putShort((short) (rectangle.top_left_y * this.scaleHeight));
+ buffer.putShort((short) (rectangle.bottom_right_x * this.scaleWidth));
+ buffer.putShort((short) (rectangle.bottom_right_y * this.scaleHeight));
+ } else {
+ buffer.putShort(rectangle.top_left_x);
+ buffer.putShort(rectangle.top_left_y);
+ buffer.putShort(rectangle.bottom_right_x);
+ buffer.putShort(rectangle.bottom_right_y);
+ }
+
+ buffer.putShort((short) this.strength);
+ }
+
+ /**
+ * Get maximum length of data.
+ * @since 1.0
+ */
+ @Override
+ public int getMaxDataLength() {
+ return 5 * ORTEConstant.SHORT_FIELD_SIZE;
+ }
+
+ /**
+ * Object to be truly send throw ORTE.
+ *
+ * @since 1.0
+ */
+ public class BoxRect
+ {
+ public short top_left_x;
+ public short top_left_y;
+ public short bottom_right_x;
+ public short bottom_right_y;
+
+ public BoxRect()
+ {}
+ }
+
+ /**
+ * When screen rotates, change scale variables to
+ * fit the destination screen.
+ *
+ * @since 1.0
+ */
+ public void setScale(int currentWidth, int currentHeight)
+ {
+ this.scaleWidth = DESTINATION_WIDTH / currentWidth;
+ this.scaleHeight = DESTINATION_HEIGHT / currentHeight;
+ }
+}
--- /dev/null
+/**
+ *
+ * This file is part of shape4a.
+ *
+ * shape4a 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.
+ *
+ * shape4a 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 shape4a. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.ocera.orte.shape4a;
+
+import java.util.regex.Pattern;
+
+import android.support.v7.app.ActionBarActivity;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.WifiLock;
+import android.os.Bundle;
+import android.support.v4.view.ViewPager;
+import android.text.InputType;
+import android.text.format.Formatter;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import org.ocera.orte.DomainApp;
+import org.ocera.orte.Manager;
+
+//TODO Better navigation (swipe sometimes miss drag).
+
+/**
+ * Main application activity, when application
+ * launch, this activity is choosen.
+ *
+ * @author jiri hubacek <jiri.hubacek@gmail.com>
+ * @version %I%, %G%
+ * @since 1.0
+ */
+public class MainActivity extends ActionBarActivity {
+ public final static Pattern IP_ADDRESS = Pattern.compile("((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))");
+
+ /**
+ * The {@link android.support.v4.view.PagerAdapter} that will provide
+ * fragments for each of the sections. We use a {@link FragmentPagerAdapter}
+ * derivative, which will keep every loaded fragment in memory. If this
+ * becomes too memory intensive, it may be best to switch to a
+ * {@link android.support.v4.app.FragmentStatePagerAdapter}.
+ */
+ SectionsPagerAdapter mSectionsPagerAdapter;
+
+ /**
+ * The {@link ViewPager} that will host the section contents.
+ */
+ ViewPager mViewPager;
+
+ private WifiManager wifiManager;
+ private WifiLock wifiLock;
+
+ private Manager orteManager;
+ private DomainApp appDomain;
+
+ private SettingsDialogFragment settingsDialogFragment = new SettingsDialogFragment();
+ private HelpDialogFragment helpDialogFragment = new HelpDialogFragment();
+
+ /**
+ * Setting up workspace.
+ *
+ * @param savedInstanceState
+ * @since 1.0
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ // Create the adapter that will return a fragment for each of the three
+ // primary sections of the activity.
+ mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
+
+ // Set up the ViewPager with the sections adapter.
+ mViewPager = (ViewPager) findViewById(R.id.pager);
+ mViewPager.setAdapter(mSectionsPagerAdapter);
+
+ // From Robot_Demo project.
+ wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+ wifiLock = (WifiLock) wifiManager.createWifiLock((
+ (android.os.Build.VERSION.SDK_INT >= 12)
+ ? WifiManager.WIFI_MODE_FULL_HIGH_PERF
+ : WifiManager.WIFI_MODE_FULL
+ ), getClass().getName());
+
+
+ // Start ORTE.
+ orteManager = new Manager("");
+ appDomain = new DomainApp();
+
+ }
+
+ /**
+ * When pause activity, release WiFi lock.
+ *
+ * @since 1.0
+ */
+ @Override
+ public void onPause()
+ {
+ super.onPause();
+
+ wifiLock.release();
+ }
+
+ /**
+ * When resume activity, acquire WiFi lock.
+ *
+ * @since 1.0
+ */
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+
+ wifiLock.acquire();
+ }
+
+ /**
+ * When switching application off.
+ *
+ * @since 1.0
+ */
+ @Override
+ public void onDestroy()
+ {
+ super.onDestroy();
+
+ if (appDomain != null) {
+ appDomain.destroy();
+ appDomain = null;
+ }
+ if (orteManager != null) {
+ orteManager.destroy();
+ orteManager = null;
+ }
+ }
+
+ /**
+ * Adding elements to menu.
+ *
+ * @since 1.0
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ /**
+ * When Settings or Help button is selected.
+ *
+ * @since 1.0
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ switch (id) {
+ case R.id.action_settings:
+ //TODO Menu Settings (prefer own activity)
+ // Ideas about settings:
+ // - input for manager's ip adresses
+ // - enable/disable scaling, destination screen size
+
+ settingsDialogFragment.show(getSupportFragmentManager(), "dialog");
+ return true;
+ case R.id.action_help:
+ //TODO Menu Help (prefer own activity)
+
+ helpDialogFragment.show(getSupportFragmentManager(), "dialog");
+ return true;
+ default:
+ // Nothing...
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
+ * one of the sections/tabs/pages.
+ */
+ public class SectionsPagerAdapter extends FragmentPagerAdapter {
+
+ public SectionsPagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ // getItem is called to instantiate the fragment for the given page.
+ // Return a PlaceholderFragment (defined as a static inner class
+ // below).
+ if (position == 0) {
+ PublisherFragment fragment = new PublisherFragment(appDomain);
+ fragment.setHasOptionsMenu(true);
+ return fragment;
+ } else {
+ SubscriberFragment fragment = new SubscriberFragment(appDomain);
+ fragment.setHasOptionsMenu(true);
+ return fragment;
+ }
+ }
+
+ @Override
+ public int getCount() {
+ // Show 2 total pages - Publisher and Subscriber
+ return 2;
+ }
+ }
+
+ /**
+ * Very easy help/about.
+ *
+ * @since 1.0
+ */
+ public class HelpDialogFragment extends DialogFragment
+ {
+ /**
+ * Create dialog window.
+ *
+ * @since 1.0
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle("Help/About")
+ .setMessage("Under construction\n" +
+ "\n" +
+ "written by jiri hubacek\n")
+ .setPositiveButton(R.string.dialog_OK, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {}
+ });
+
+ return builder.create();
+ }
+ }
+
+ /**
+ * Set up IP addresses of other managers.
+ *
+ * @since 1.0
+ */
+ public class SettingsDialogFragment extends DialogFragment
+ {
+ private EditText om;
+
+ /**
+ * Create dialog window.
+ *
+ * @since 1.0
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState)
+ {
+ // Strings should be done better way, like
+ // centralized in strings.xml
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle("Your IP is " + Formatter.formatIpAddress(wifiManager.getConnectionInfo().getIpAddress()) + ",\nadd other managers:")
+ .setView(text())
+ .setPositiveButton(R.string.dialog_OK, new DialogInterface.OnClickListener() {
+
+ /**
+ * When IP addresses of managers changes,
+ * destroy manager and create new one.
+ *
+ * @since 1.0
+ */
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ if (IP_ADDRESS.matcher(om.getText()).matches()) {
+ if (orteManager != null) orteManager.destroy();
+
+ String managers[] = new String[1];
+ managers[0] = om.getText().toString();
+
+ orteManager = new Manager(managers);
+ }
+ }
+ })
+ .setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+
+ return builder.create();
+ }
+
+ /**
+ * SeekBar for setting-up strength of publishers.
+ *
+ * @return Layout of SeekBar.
+ * @since 1.0
+ */
+ private View text(){
+ LinearLayout l = new LinearLayout(getActivity());
+ l.setOrientation(LinearLayout.VERTICAL);
+
+ om = new EditText(getActivity());
+ om.setInputType(InputType.TYPE_CLASS_PHONE);
+ om.setText("192.168.1.108");
+
+ l.addView(om);
+ return l;
+ }
+ }
+
+}
--- /dev/null
+/**
+ *
+ * This file is part of shape4a.
+ *
+ * shape4a 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.
+ *
+ * shape4a 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 shape4a. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.ocera.orte.shape4a;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+
+import org.ocera.orte.DomainApp;
+
+/**
+ * Fragment containing publishing workspace.
+ *
+ * @author jiri hubacek <jiri.hubacek@gmail.com>
+ * @version %I%, %G%
+ * @since 1.0
+ */
+public class PublisherFragment extends Fragment {
+ private static final int REDRAW_INTERVAL = 50;
+ private static final int STRENGTH_MAX = 5;
+
+ private View rootView;
+ private PublisherView publisherView;
+
+ private Handler handler = new Handler();
+ private Runnable redraw = new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ publisherView.countShapes();
+ publisherView.invalidate();
+ handler.postDelayed(this, REDRAW_INTERVAL);
+ }
+ };
+
+ NewDialogFragment newDialogFragment = new NewDialogFragment();
+ PublisherSettingsDialogFragment publisherSettingsDialogFragment = new PublisherSettingsDialogFragment();
+
+ private DomainApp appDomain;
+
+ /**
+ * Constructor just stores appDomain variable.
+ *
+ * @param appDomain
+ * @since 1.0
+ */
+ public PublisherFragment(DomainApp appDomain)
+ {
+ this.appDomain = appDomain;
+ }
+
+ /**
+ * When screen orientation is changed,
+ * scale recalculation is needed.
+ *
+ * @since 1.0
+ */
+ @Override
+ public void onConfigurationChanged(Configuration newConfig)
+ {
+ for (PublisherShape s : this.publisherView.shapes) {
+ s.setScale(getActivity().getWindowManager().getDefaultDisplay().getWidth(), getActivity().getWindowManager().getDefaultDisplay().getHeight());
+ }
+ }
+
+ /**
+ * Setting up workspace, adding publisherView
+ * and timer (handler) for drawing objects.
+ *
+ * @since 1.0
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ this.rootView = inflater.inflate(R.layout.fragment_publisher, container, false);
+ this.publisherView = (PublisherView) this.rootView.findViewById(R.id.publisher_view);
+ this.handler.postDelayed(redraw, REDRAW_INTERVAL);
+
+ return this.rootView;
+ }
+
+ /**
+ * Creating menu.
+ *
+ * @since 1.0
+ */
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
+ {
+ inflater.inflate(R.menu.publisher, menu);
+ }
+
+ /**
+ * All created publishers are in menu.
+ *
+ * @since 1.0
+ */
+ @Override
+ public void onPrepareOptionsMenu(Menu menu)
+ {
+ for (PublisherShape shape : publisherView.shapes) {
+ menu.add(0, publisherView.shapes.indexOf(shape), 20 + publisherView.shapes.indexOf(shape), "#" + publisherView.shapes.indexOf(shape) + " " + shape.getColorName() + " " + shape.getShapeName());
+ }
+ }
+
+ /**
+ * Select settings of publishers
+ * or add new publisher.
+ *
+ * @since 1.0
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item)
+ {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+
+ if (id >= 0 && id < publisherView.shapes.size()) {
+ publisherSettingsDialogFragment.setId(id);
+ publisherSettingsDialogFragment.show(getFragmentManager(), "dialog");
+ } else {
+ switch (id) {
+ case R.id.action_new:
+ newDialogFragment.show(getFragmentManager(), "dialog");
+ break;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * Dialog for adding new publisher
+ * throw action bar button +.
+ *
+ * @since 1.0
+ */
+ public class NewDialogFragment extends DialogFragment
+ {
+ /*
+ * Selection of colors is badly solved,
+ * it should be altered..
+ *
+ */
+ private String[] colors = new String[5];
+
+ /**
+ * In constructor, make array
+ * of colors.
+ *
+ * @since 1.0
+ */
+ public NewDialogFragment()
+ {
+ // Texts should be done better way,
+ // like centralized in strings.xml
+
+ colors[0] = "Blue";
+ colors[1] = "Green";
+ colors[2] = "Red";
+ colors[3] = "Black";
+ colors[4] = "Yellow";
+ }
+
+ /**
+ * Creating dialog for new publisher.
+ *
+ * @since 1.0
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_newPublisher)
+ .setItems(colors, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ // new publisher
+
+ publisherView.addShape(which, appDomain);
+
+ for (PublisherShape s : publisherView.shapes) {
+ s.setScale(getActivity().getWindowManager().getDefaultDisplay().getWidth(), getActivity().getWindowManager().getDefaultDisplay().getHeight());
+ }
+
+ getActivity().supportInvalidateOptionsMenu();
+ }
+ })
+ .setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ }
+ });
+ return builder.create();
+
+ }
+ }
+
+ /**
+ * When click on shape in Action Bar menu.
+ *
+ * @since 1.0
+ */
+ public class PublisherSettingsDialogFragment extends DialogFragment
+ {
+ private int shapeId;
+ private int shapeStrength;
+ private SeekBar seekStrength;
+
+ /**
+ * No constructor needed.
+ *
+ * @since 1.0
+ */
+ public PublisherSettingsDialogFragment()
+ {}
+
+ /**
+ * Set wanted publisher's dialog.
+ *
+ * @param i Index of publisher.
+ * @since 1.0
+ */
+ public void setId(int i)
+ {
+ this.shapeId = i;
+ this.shapeStrength = publisherView.shapes.get(this.shapeId).getStrength();
+ }
+
+ /**
+ * Creating dialog for publisher's settings.
+ *
+ * @since 1.0
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle("#" + this.shapeId + " " + publisherView.shapes.get(this.shapeId).getColorName() + " " + publisherView.shapes.get(this.shapeId).getShapeName() + " strength:")
+ .setView(seekBar())
+ .setPositiveButton(R.string.dialog_OK, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ publisherView.shapes.get(shapeId).setStrength(shapeStrength);
+ }
+ })
+ .setNeutralButton(R.string.dialog_delete, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ publisherView.shapes.get(shapeId).killMe();
+ publisherView.shapes.remove(shapeId);
+ getActivity().supportInvalidateOptionsMenu();
+ }
+ })
+ .setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ }
+ });
+ return builder.create();
+ }
+
+ /**
+ * SeekBar for setting-up strength of publishers.
+ *
+ * @return Layout of SeekBar.
+ * @since 1.0
+ */
+ private View seekBar(){
+ LinearLayout l = new LinearLayout(getActivity());
+ l.setOrientation(LinearLayout.VERTICAL);
+
+ seekStrength = new SeekBar(getActivity());
+ seekStrength.setMax(STRENGTH_MAX);
+ seekStrength.setProgress(shapeStrength);
+ seekStrength.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
+ {
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
+ {
+ shapeStrength = progress;
+ }
+ });
+
+ l.addView(seekStrength);
+ return l;
+ }
+ }
+}
--- /dev/null
+/**
+ *
+ * This file is part of shape4a.
+ *
+ * shape4a 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.
+ *
+ * shape4a 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 shape4a. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.ocera.orte.shape4a;
+
+import org.ocera.orte.DomainApp;
+import org.ocera.orte.Publication;
+import org.ocera.orte.types.NtpTime;
+import org.ocera.orte.types.PublProp;
+
+import android.graphics.Color;
+import android.graphics.Path;
+import android.graphics.Path.FillType;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.OvalShape;
+import android.graphics.drawable.shapes.PathShape;
+import android.graphics.drawable.shapes.RectShape;
+import android.graphics.drawable.shapes.Shape;
+
+/**
+ * Some additional parameters for {@link ShapeDrawable}
+ * to make it Publisher-friendly.
+ *
+ * @author jiri hubacek <jiri.hubacek@gmail.com>
+ * @version %I%, %G%
+ * @since 1.0
+ */
+public class PublisherShape extends ShapeDrawable
+{
+ // Prefer at least 48x48 shape size (Full asset), for more
+ // info, please refer to http://developer.android.com/
+
+ private static final int SHAPE_WIDTH = 48;
+ private static final int SHAPE_HEIGHT = 48;
+ private boolean manual;
+ private int incX, incY;
+
+ private PublProp publisherProperties;
+ private NtpTime persistence;
+
+ public Publication publication;
+ public Box box;
+
+ /**
+ * Set new {@link Shape}, strength and color.
+ *
+ * @param s strength, shape
+ * @param c color
+ * @param appDomain
+ * @since 1.0
+ */
+ public PublisherShape(int s, int c, DomainApp appDomain)
+ {
+ super((s == 0)
+ ?new RectShape()
+ :((s == 1)
+ ?new OvalShape()
+ :((s == 2)
+ ?new PathShape(new Path(), 96, 96)
+ :new RectShape()
+ )
+ )
+ );
+
+ if (s == 2) { // fix triangle
+ this.setShape(new PathShape(PublisherShape.returnTrianglePath(), 96, 96));
+ }
+
+ this.manual = false;
+ this.persistence = new NtpTime(5);
+
+ this.box = new Box(appDomain, PublisherShape.getColorName(c));
+ this.publisherProperties = new PublProp(this.box.getTopic(),
+ "Box",
+ this.persistence,
+ s+1);
+ this.publication = appDomain.createPublication(this.publisherProperties, this.box);
+
+ this.box.strength = s;
+ this.box.color = c;
+
+ this.getPaint().setColor(PublisherShape.getColorConstant(c));
+ this.setPadding(0, 0, 0, 0);
+ this.setBounds(0, 0, SHAPE_WIDTH, SHAPE_HEIGHT);
+
+ //Log.d("PublisherShape", "s: "+s+", c: "+c+", left: "+this.getBounds().left+", top: "+this.getBounds().top+", right: "+this.getBounds().right+", bottom: "+this.getBounds().bottom);
+ }
+
+ /**
+ * Update parameters of object to send.
+ *
+ * @return Object to send.
+ * @since 1.0
+ */
+ public Box toSend()
+ {
+ this.box.rectangle.top_left_x = (short) this.getBounds().left;
+ this.box.rectangle.top_left_y = (short) this.getBounds().top;
+ this.box.rectangle.bottom_right_x = (short) this.getBounds().right;
+ this.box.rectangle.bottom_right_y = (short) this.getBounds().bottom;
+
+ return this.box;
+ }
+
+ /**
+ * Revert proprietary color to android color constant.
+ *
+ * @param c Proprietary value of color.
+ * @return Android color constant.
+ * @since 1.0
+ */
+ public static int getColorConstant(int c)
+ {
+ switch (c) {
+ case 0:
+ return Color.BLUE;
+ case 1:
+ return Color.GREEN;
+ case 2:
+ return Color.RED;
+ case 3:
+ return Color.BLACK;
+ case 4:
+ return Color.YELLOW;
+ default:
+ return 0;
+ }
+ }
+
+ /**
+ * Revert proprietary color to android color constant.
+ *
+ * @return Android color constant.
+ * @since 1.0
+ */
+ public int getColorConstant()
+ {
+ return PublisherShape.getColorConstant(this.box.color);
+ }
+
+ /**
+ * Revert proprietary color to word.
+ *
+ * @param c Proprietary value of color.
+ * @return Name of color.
+ * @since 1.0
+ */
+ public static String getColorName(int c)
+ {
+ // should be done better way
+ // texts shouldn't be static
+ // but dynamically mapped to
+ // strings.xml
+
+ switch (c) {
+ case 0:
+ return "Blue";
+ case 1:
+ return "Green";
+ case 2:
+ return "Red";
+ case 3:
+ return "Black";
+ case 4:
+ return "Yellow";
+ default:
+ return "NONE";
+ }
+ }
+
+ /**
+ * Revert proprietary color to word.
+ *
+ * @return Name of color.
+ * @since 1.0
+ */
+ public String getColorName()
+ {
+ return PublisherShape.getColorName(this.box.color);
+ }
+
+ /**
+ * Revert strength to shape.
+ *
+ * @return Name of shape.
+ * @since 1.0
+ */
+ public String getShapeName()
+ {
+ switch (this.box.strength) {
+ case 0:
+ return "Square";
+ case 1:
+ return "Circle";
+ case 2:
+ return "Triangle";
+ default:
+ return "NONE";
+ }
+ }
+
+ /* getters, setters */
+
+ /**
+ * Set value of incX - how much move object
+ * in x-axis direction.
+ *
+ * @param x
+ * @since 1.0
+ */
+ public void setIncX(int x) { this.incX = x; }
+ /**
+ * Get value of incX - how much move object
+ * in x-axis direction.
+ *
+ * @return Distance to move in x-axis.
+ * @since 1.0
+ */
+ public int getIncX() { return this.incX; }
+
+ /**
+ * Set value of incY - how much move object
+ * in y-axis direction.
+ *
+ * @param y
+ * @since 1.0
+ */
+ public void setIncY(int y) { this.incY = y; }
+ /**
+ * Get value of incY - how much move object
+ * in y-axis direction.
+ *
+ * @return Distance to move in y-axis.
+ * @since 1.0
+ */
+ public int getIncY() { return this.incY; }
+
+ /**
+ * Set strength of publishing.
+ *
+ * @param s
+ * @since 1.0
+ */
+ public void setStrength(int s) {
+ PublProp properties = this.publication.getProperties();
+ properties.setStrength(s);
+ this.publication.setProperties(properties);
+ }
+ /**
+ * Get strength of publishing.
+ *
+ * @return Strength of publishing.
+ * @since 1.0
+ */
+ public int getStrength() { return this.publication.getProperties().getStrength(); }
+
+ /**
+ * Set if object is moved automatically or by
+ * user.
+ * TRUE - by user
+ * FALSE - automatically
+ *
+ * @param b
+ * @since 1.0
+ */
+ public void setManual(boolean b) { this.manual = b; }
+ /**
+ * Get if object is moved automatically or by
+ * user.
+ *
+ * @return How is object moved.
+ * @since 1.0
+ */
+ public boolean getManual() { return this.manual; }
+
+ /**
+ * Make triangle path for new instance.
+ *
+ * @return Triangle path.
+ * @since 1.0
+ */
+ public static Path returnTrianglePath()
+ {
+ Path path = new Path();
+ path.setFillType(FillType.EVEN_ODD);
+ path.moveTo(48, 0);
+ path.lineTo(96, 96);
+ path.lineTo(0, 96);
+ path.lineTo(48, 0);
+ path.close();
+
+ return path;
+ }
+
+ /**
+ * When publisher is removed, destroy publication.
+ *
+ * @since 1.0
+ */
+ public void killMe()
+ {
+ this.publication.destroy();
+ }
+
+ /**
+ * Pass parameters to box.
+ *
+ * @param currentWidth
+ * @param currentHeight
+ * @since 1.0
+ */
+ public void setScale(int currentWidth, int currentHeight)
+ {
+ this.box.setScale(currentWidth, currentHeight);
+ }
+}
--- /dev/null
+/**
+ *
+ * This file is part of shape4a.
+ *
+ * shape4a 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.
+ *
+ * shape4a 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 shape4a. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.ocera.orte.shape4a;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import org.ocera.orte.DomainApp;
+
+/**
+ * View, where publisher objects are drawn.
+ *
+ * @author jiri hubacek <jiri.hubacek@gmail.com>
+ * @version %I%, %G%
+ * @since 1.0
+ */
+public class PublisherView extends View
+{
+ private static final int STEP_X = 2;
+ private static final int STEP_Y = 2;
+
+ public ArrayList<PublisherShape> shapes = new ArrayList<PublisherShape>();
+
+ private Random random = new Random();
+
+ /**
+ * Just compatibility method.
+ *
+ * @param context
+ * @param attrs
+ * @since 1.0
+ */
+ public PublisherView(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+ }
+
+ /**
+ * Update publisher shape's position.
+ *
+ * @since 1.0
+ */
+ public void countShapes()
+ {
+ for (PublisherShape shape : shapes) {
+ if (!shape.getManual()) {
+ if (shape.getBounds().left <= 0) shape.setIncX(STEP_X);
+ if (shape.getBounds().top <= 0) shape.setIncY(STEP_Y);
+ if (shape.getBounds().right >= getWidth()) shape.setIncX(-STEP_X);
+ if (shape.getBounds().bottom >= getHeight()) shape.setIncY(-STEP_Y);
+ } else {
+ shape.setIncX(0);
+ shape.setIncY(0);
+ }
+
+ shape.setBounds(shape.getBounds().left + shape.getIncX(), shape.getBounds().top + shape.getIncY(), shape.getBounds().right + shape.getIncX(), shape.getBounds().bottom + shape.getIncY());
+ shape.publication.send(shape.toSend());
+ }
+ }
+
+ /**
+ * Draw all publisher objects.
+ *
+ * @since 1.0
+ */
+ @Override
+ protected void onDraw(Canvas canvas)
+ {
+ for (PublisherShape shape : shapes) {
+ shape.draw(canvas);
+ }
+ }
+
+ @Override
+ public boolean performClick()
+ {
+ return super.performClick();
+ }
+
+ /**
+ * When touch the publisher object, start manual
+ * mode and let user change position of object. When
+ * user finishes, just generate random direction and
+ * let object moving automatically again.
+ *
+ * @since 1.0
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event)
+ {
+ int myX = 0, myY = 0;
+
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ myX = (int) event.getX();
+ myY = (int) event.getY();
+
+ for (PublisherShape shape : shapes) {
+ if (myX <= shape.getBounds().right
+ && myX >= shape.getBounds().left
+ && myY >= shape.getBounds().top
+ && myY <= shape.getBounds().bottom) {
+ shape.setManual(true);
+ break;
+ }
+ }
+
+ return true;
+ case MotionEvent.ACTION_MOVE:
+ myX = (int) event.getX();
+ myY = (int) event.getY();
+
+ for (PublisherShape shape : shapes) {
+ if (shape.getManual()) {
+ shape.setBounds((int) (myX - shape.getShape().getWidth()/2), (int) (myY - shape.getShape().getHeight()/2), (int) (myX + shape.getShape().getWidth()/2), (int) (myY + shape.getShape().getHeight()/2));
+ break;
+ }
+ }
+
+ return true;
+ case MotionEvent.ACTION_UP:
+ myX = (int) event.getX();
+ myY = (int) event.getY();
+
+ for (PublisherShape shape : shapes) {
+ if (myX <= shape.getBounds().right
+ && myX >= shape.getBounds().left
+ && myY >= shape.getBounds().top
+ && myY <= shape.getBounds().bottom) {
+ shape.setManual(false);
+ shape.setIncX(STEP_X * (1 -2*random.nextInt(2)));
+ shape.setIncY(STEP_Y * (1 -2*random.nextInt(2)));
+ }
+ }
+
+ return true;
+ default:
+ return super.onTouchEvent(event) || this.performClick();
+ }
+ }
+
+ /**
+ * When OK is selected on {@link NewDialogFragment},
+ * this method is called to add new publisher object.
+ *
+ * @param color
+ * @param appDomain
+ * @since 1.0
+ */
+ public void addShape(int color, DomainApp appDomain)
+ {
+ this.shapes.add(new PublisherShape(random.nextInt(3), color, appDomain));
+ }
+}
--- /dev/null
+/**
+ *
+ * This file is part of shape4a.
+ *
+ * shape4a 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.
+ *
+ * shape4a 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 shape4a. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.ocera.orte.shape4a;
+
+import android.graphics.Canvas;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.OvalShape;
+import android.graphics.drawable.shapes.PathShape;
+import android.graphics.drawable.shapes.RectShape;
+import android.view.View;
+
+import org.ocera.orte.DomainApp;
+import org.ocera.orte.Subscription;
+import org.ocera.orte.SubscriptionCallback;
+import org.ocera.orte.types.MessageData;
+import org.ocera.orte.types.NtpTime;
+import org.ocera.orte.types.RecvInfo;
+import org.ocera.orte.types.SubsProp;
+import org.ocera.orte.types.ORTEConstant;
+
+/**
+ * Subscribing objects are made by this class.
+ *
+ * @author jiri hubacek <jiri.hubacek@gmail.com>
+ * @version %I%, %G%
+ * @since 1.0
+ */
+public class SubscriberElement extends SubscriptionCallback
+{
+ private Subscription subscription;
+
+ private NtpTime deadline;
+ private NtpTime minSeparation;
+
+ private Box box;
+ private ShapeDrawable shape;
+
+ private View parentView;
+
+ private boolean receiving;
+ private boolean enabled;
+
+ /**
+ * Set default variables of subscriber's object.
+ *
+ * @param appDomain
+ * @param color Topic is dependent on color.
+ * @since 1.0
+ */
+ public SubscriberElement(DomainApp appDomain, int color, View v) {
+ this.deadline = new NtpTime(6);
+ this.minSeparation = new NtpTime(0);
+
+ this.box = new Box(appDomain, PublisherShape.getColorName(color));
+ SubsProp subscriberProperties = new SubsProp(this.box.getTopic(),
+ "Box",
+ this.minSeparation,
+ this.deadline,
+ ORTEConstant.IMMEDIATE,
+ ORTEConstant.BEST_EFFORTS,
+ 0);
+
+ this.subscription = appDomain.createSubscription(subscriberProperties, this.box, this);
+
+ this.shape = new ShapeDrawable();
+ this.shape.getPaint().setColor(PublisherShape.getColorConstant(color));
+
+ this.setShape();
+
+ this.parentView = v;
+
+ this.enabled = true;
+ }
+
+ /**
+ * What should be done when new data are received.
+ *
+ * @param info
+ * @param msg
+ * @since 1.0
+ */
+ public void callback(RecvInfo info, MessageData msg)
+ {
+ switch (info.getRecvStatus()) {
+ case ORTEConstant.NEW_DATA:
+ this.receiving = true;
+ //Log.d("SubscriberElement", "new data: " + (int) ((Box) msg).strength + "(was "+ this.box.strength +"); " + ((Box) msg).rectangle.top_left_x + ", " + ((Box) msg).rectangle.top_left_y + ", " +((Box) msg).rectangle.bottom_right_x + ", " + ((Box) msg).rectangle.bottom_right_y);
+
+ this.shape.getBounds().left = this.box.rectangle.top_left_x;
+ this.shape.getBounds().top = this.box.rectangle.top_left_y;
+ this.shape.getBounds().right = this.box.rectangle.bottom_right_x;
+ this.shape.getBounds().bottom = this.box.rectangle.bottom_right_y;
+
+ this.setShape();
+
+ this.parentView.postInvalidate();
+ break;
+ case ORTEConstant.DEADLINE:
+ this.receiving = false;
+ this.parentView.postInvalidate();
+ break;
+ }
+ }
+
+ /**
+ * Draw shape, which is private object.
+ *
+ * @param canvas
+ * @since 1.0
+ */
+ public void drawMe(Canvas canvas)
+ {
+ this.shape.draw(canvas);
+ }
+
+ /**
+ * Set desired shape of object.
+ *
+ * @since 1.0
+ */
+ public void setShape()
+ {
+ switch (this.box.strength) {
+ case 0:
+ this.shape.setShape(new RectShape());
+ break;
+ case 1:
+ this.shape.setShape(new OvalShape());
+ break;
+ case 2:
+ this.shape.setShape(new PathShape(PublisherShape.returnTrianglePath(), 96, 96));
+ break;
+ default:
+ this.shape.setShape(new RectShape());
+ }
+ }
+
+ /**
+ * Getter for enabled value. Should be object
+ * drawn or not?
+ *
+ * @return Enabled?
+ * @since 1.0
+ */
+ public boolean getEnabled() { return this.enabled; }
+
+ /**
+ * Set value enabled. Should be object
+ * drawn or not?
+ *
+ * @param b Enable?
+ * @since 1.0
+ */
+ public void setEnabled(boolean b) { this.enabled = b; }
+
+ /**
+ * Getter for receiving value. Should be object
+ * drawn or not?
+ *
+ * @return Receiving?
+ * @since 1.0
+ */
+ public boolean getReceiving() { return this.receiving; }
+
+ /**
+ * Set value receiving. Should be object
+ * drawn or not?
+ *
+ * @param b Receiving?
+ * @since 1.0
+ */
+ public void setReceiving(boolean b) { this.receiving = b; }
+
+ /**
+ * Min. Separation value is used for desired update delay.
+ *
+ * @return NtpTime value of Min. Separation.
+ * @since 1.0
+ */
+ public NtpTime getMinSeparation()
+ {
+ return this.subscription.getProperties().getMinSeparation();
+ }
+
+ /**
+ * Min. Separation value is used for desired update delay,
+ * this is setter for this value.
+ *
+ * @param newMinSeparation
+ * @since 1.0
+ */
+ public void setMinSeparation(NtpTime newMinSeparation)
+ {
+ SubsProp properties = this.subscription.getProperties();
+ properties.setMinSeparation(newMinSeparation);
+ this.subscription.setProperties(properties);
+ }
+
+ /**
+ * Pass parameters to box.
+ *
+ * @param currentWidth
+ * @param currentHeight
+ * @since 1.0
+ */
+ public void setScale(int currentWidth, int currentHeight)
+ {
+ this.box.setScale(currentWidth, currentHeight);
+ }
+
+}
--- /dev/null
+/**
+ *
+ * This file is part of shape4a.
+ *
+ * shape4a 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.
+ *
+ * shape4a 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 shape4a. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.ocera.orte.shape4a;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+
+import org.ocera.orte.DomainApp;
+import org.ocera.orte.types.NtpTime;
+
+/**
+ * Fragment containing subscribing workspace.
+ *
+ * @author jiri hubacek <jiri.hubacek@gmail.com>
+ * @version %I%, %G%
+ * @since 1.0
+ */
+public class SubscriberFragment extends Fragment {
+ private static final int MINSEPARATION_MAX = 5;
+
+ private View rootView;
+ private SubscriberView subscriberView;
+ private DomainApp appDomain;
+
+ private SubscriberSettingsDialogFragment subscriberSettingsDialogFragment = new SubscriberSettingsDialogFragment();
+
+ /**
+ * Constructor just stores appDomain variable.
+ *
+ * @param appDomain
+ * @since 1.0
+ */
+ public SubscriberFragment(DomainApp appDomain)
+ {
+ this.appDomain = appDomain;
+ }
+
+ /**
+ * When screen orientation is changed,
+ * scale recalculation is needed.
+ *
+ * @since 1.0
+ */
+ @Override
+ public void onConfigurationChanged(Configuration newConfig)
+ {
+ for (SubscriberElement e : this.subscriberView.elements) {
+ e.setScale(getActivity().getWindowManager().getDefaultDisplay().getWidth(), getActivity().getWindowManager().getDefaultDisplay().getHeight());
+ }
+ }
+
+ /**
+ * Setting up workspace, adding publisherView
+ * and timer (handler) for drawing objects.
+ *
+ * @since 1.0
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ this.rootView = inflater.inflate(R.layout.fragment_subscriber, container, false);
+ this.subscriberView = (SubscriberView) this.rootView.findViewById(R.id.subscriber_view);
+ this.subscriberView.addElements(this.appDomain);
+ for (SubscriberElement e : this.subscriberView.elements) {
+ e.setScale(getActivity().getWindowManager().getDefaultDisplay().getWidth(), getActivity().getWindowManager().getDefaultDisplay().getHeight());
+ }
+ return this.rootView;
+ }
+
+ /**
+ * Creating menu.
+ *
+ * @since 1.0
+ */
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
+ {
+ inflater.inflate(R.menu.subscriber, menu);
+ }
+
+ /**
+ * Setting up subscriber objects.
+ *
+ * @since 1.0
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item)
+ {
+ int id = 0;
+ switch (item.getItemId()) {
+ case R.id.action_blue:
+ id = 0;
+ break;
+ case R.id.action_green:
+ id = 1;
+ break;
+ case R.id.action_red:
+ id = 2;
+ break;
+ case R.id.action_black:
+ id = 3;
+ break;
+ case R.id.action_yellow:
+ id = 4;
+ break;
+ default:
+ }
+
+ subscriberSettingsDialogFragment.setId(id);
+ subscriberSettingsDialogFragment.show(getFragmentManager(), "dialog");
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * When click on shape in Action Bar menu.
+ *
+ * @since 1.0
+ */
+ public class SubscriberSettingsDialogFragment extends DialogFragment
+ {
+ private int eId, ms;
+ private NtpTime minSeparation;
+ private SeekBar seekMinSeparation;
+
+ /**
+ * Set wanted publisher's dialog.
+ *
+ * @param i Index of publisher.
+ * @since 1.0
+ */
+ public void setId(int i)
+ {
+ this.eId = i;
+ this.minSeparation = subscriberView.elements.get(this.eId).getMinSeparation();
+ this.ms = 0;
+ }
+
+ /**
+ * Creating dialog for subscriber's settings.
+ *
+ * @since 1.0
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(PublisherShape.getColorName(this.eId) + " settings")
+ .setView(seekBar())
+ .setPositiveButton(R.string.dialog_OK, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ minSeparation = new NtpTime(ms);
+ subscriberView.elements.get(eId).setMinSeparation(minSeparation);
+ subscriberView.elements.get(eId).setEnabled(true);
+ }
+ })
+ .setNeutralButton(subscriberView.elements.get(eId).getEnabled()?R.string.dialog_delete:R.string.dialog_add, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (subscriberView.elements.get(eId).getEnabled()) {
+ subscriberView.elements.get(eId).setEnabled(false);
+ } else {
+ minSeparation = new NtpTime(ms);
+ subscriberView.elements.get(eId).setMinSeparation(minSeparation);
+ subscriberView.elements.get(eId).setEnabled(true);
+ }
+ }
+ })
+ .setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {}
+ });
+ return builder.create();
+ }
+
+ /**
+ * SeekBar for setting-up min. separation of subscribers.
+ *
+ * @return Layout of SeekBar.
+ * @since 1.0
+ */
+ private View seekBar(){
+ LinearLayout l = new LinearLayout(getActivity());
+ l.setOrientation(LinearLayout.VERTICAL);
+
+ seekMinSeparation = new SeekBar(getActivity());
+ seekMinSeparation.setMax(MINSEPARATION_MAX);
+ seekMinSeparation.setProgress(0);
+ seekMinSeparation.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
+ {
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
+ {
+ ms = progress;
+ }
+ });
+
+ l.addView(seekMinSeparation);
+ return l;
+ }
+ }
+}
--- /dev/null
+/**
+ *
+ * This file is part of shape4a.
+ *
+ * shape4a 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.
+ *
+ * shape4a 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 shape4a. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.ocera.orte.shape4a;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+
+import org.ocera.orte.DomainApp;
+
+/**
+ * View, where subscriber objects are drawn.
+ *
+ * @author jiri hubacek <jiri.hubacek@gmail.com>
+ * @version %I%, %G%
+ * @since 1.0
+ */
+public class SubscriberView extends View {
+ public ArrayList<SubscriberElement> elements = new ArrayList<SubscriberElement>();
+
+ /**
+ * Default constructor.
+ *
+ * @param context
+ * @param attrs
+ */
+ public SubscriberView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ /**
+ * When drawing, draw all subscribers shapes.
+ *
+ * @param canvas
+ */
+ @Override
+ protected void onDraw(Canvas canvas)
+ {
+ for (SubscriberElement element : elements) {
+ if (element.getReceiving() && element.getEnabled()) element.drawMe(canvas);
+ }
+ }
+
+ /**
+ * Make objects of all colors ready to subscribe.
+ *
+ * @param appDomain
+ */
+ public void addElements(DomainApp appDomain)
+ {
+ for (int i = 0; i < 5; i++) {
+ this.elements.add(new SubscriberElement(appDomain, i, this));
+ }
+ }
+}