diff --git a/.gitignore b/.gitignore index bfcf66c..c5f82c3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,62 +1,62 @@ -# Built application files -*.apk -*.ap_ - -# Files for the Dalvik VM -*.dex - -# Java class files -*.class - -# Generated files -bin/ -gen/ -doc/ - -# Proguard folder generated by Eclipse -proguard/ - -# Log Files -*.log - -# Built application files -/*/build/ - -# Crashlytics configuations -com_crashlytics_export_strings.xml -crashlytics-build.properties -crashlytics.properties - -# Local configuration file (sdk path, etc) -local.properties - -# Gradle generated files -.gradle/ - -# Signing files -.signing/ - -# User-specific configurations -.idea/libraries/ -.idea/workspace.xml -.idea/tasks.xml -.idea/.name -.idea/compiler.xml -.idea/copyright/profiles_settings.xml -.idea/encodings.xml -.idea/misc.xml -.idea/modules.xml -.idea/scopes/scope_settings.xml -.idea/vcs.xml -*.iml - -# OS-specific files -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db -*~ +# Built application files +*.apk +*.ap_ + +# Files for the Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +doc/ + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Built application files +/*/build/ + +# Crashlytics configuations +com_crashlytics_export_strings.xml +crashlytics-build.properties +crashlytics.properties + +# Local configuration file (sdk path, etc) +local.properties + +# Gradle generated files +.gradle/ + +# Signing files +.signing/ + +# User-specific configurations +.idea/libraries/ +.idea/workspace.xml +.idea/tasks.xml +.idea/.name +.idea/compiler.xml +.idea/copyright/profiles_settings.xml +.idea/encodings.xml +.idea/misc.xml +.idea/modules.xml +.idea/scopes/scope_settings.xml +.idea/vcs.xml +*.iml + +# OS-specific files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +*~ #*# \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml index 29ab470..f0823bb 100644 --- a/.idea/codeStyleSettings.xml +++ b/.idea/codeStyleSettings.xml @@ -1,174 +1,174 @@ - - - - - - - + + + + + + + diff --git a/.idea/copyright/Copyright_Vlad_Mihalachi.xml b/.idea/copyright/Copyright_Vlad_Mihalachi.xml index 52b8817..866a560 100644 --- a/.idea/copyright/Copyright_Vlad_Mihalachi.xml +++ b/.idea/copyright/Copyright_Vlad_Mihalachi.xml @@ -1,9 +1,9 @@ - - - + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 286ffea..5cb8949 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,23 +1,23 @@ - - - - - - - + + + + + + + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index a259df6..e070203 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,14 +1,14 @@ - - - + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml index 3b31283..6933c1e 100644 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -1,7 +1,7 @@ - - - + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE index 3dc9644..eda548a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,678 +1,678 @@ - - 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: - - {project} Copyright (C) {year} {fullname} - 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]. - - + + 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: + + {project} Copyright (C) {year} {fullname} + 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 diff --git a/README.md b/README.md index a9969f3..a3976c7 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,60 @@ -# Turbo Editor -[![Crowdin](https://d322cqt584bo4o.cloudfront.net/turbo-client/localized.png)](https://crowdin.com/project/turbo-client) - -Simple, powerful and Open Source text editor for Android licensed under the GPLv3 license. - -### Download -[![Play Store](http://developer.android.com/images/brand/en_generic_rgb_wo_60.png)](http://play.google.com/store/apps/details?id=com.maskyn.fileeditorpro) - -[![F-Droid](https://lh5.googleusercontent.com/-zezQqsBye0c/VCUpPVjcKEI/AAAAAAAAAIQ/HbcG5f1qMIw/w129-h45-no/getitonfdroid.png)](https://f-droid.org/repository/browse/?fdid=com.maskyn.fileeditorpro) - -### Contribute -You can contribute to this project in many ways: -* Browse our issues, comment on proposals, report bugs. -* Help to translate the application on [Crowdin][crowdin] -* Be a part of the Google Plus [Community][community googleplus] -* Discuss with us on [XDA thread][xda thread] -* Help to maintain this project active and [Donate][donate] - ------- - -###Donate -[![Paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=26VWS2TSAMUJA) - -[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=vmihalachi&url=https://github.com/vmihalachi/turbo-editor&title=Turbo Editor&language=java&tags=github&category=software) - ------- - -###Images -![](https://lh3.googleusercontent.com/-0GHukwGQPW4/VCUpEhKnZCI/AAAAAAAAAH4/cclI70K79_Q/w347-h520-no/PhoneCustom_7.png)![](https://lh3.googleusercontent.com/-OvazluFl_QQ/VCUo9DAje9I/AAAAAAAAAHQ/i7n1uCpU1hE/w347-h520-no/PhoneCustom_1.png)![](https://lh4.googleusercontent.com/-zh4CYdQPecg/VCUpD3QXpAI/AAAAAAAAAHw/ulL5-V0iJUw/w347-h520-no/PhoneCustom_6.png)![](https://lh4.googleusercontent.com/-LT3k4z9JHo8/VCUo_0jnZRI/AAAAAAAAAHg/Npk9UlkXIV8/w347-h520-no/PhoneCustom_4.png)![](https://lh5.googleusercontent.com/-hXvsf-WYvBs/VCUo9sYfR-I/AAAAAAAAAHY/TTfAgiV_7ko/w347-h520-no/PhoneCustom_3.png)![](https://lh6.googleusercontent.com/-Qib82pK6mZU/VCUpAgYmUdI/AAAAAAAAAHo/zoPVmwcatbQ/w347-h520-no/PhoneCustom_5.png)![](https://lh5.googleusercontent.com/-SERL7X-JHuc/VCax0QSlCGI/AAAAAAAAAJA/hu8dvbvJGBM/w375-h563-no/PhoneCustom_2.png) ------- - -### Developer -[Vlad Mihalachi][developer site] - ------- - -### A special thanks to.. -* [Dumitru Grubii][contributor dumitru grubii] for the icon -* All the translators -* You? - ------- - -### License -Turbo Client is made available under the terms of the [GPLv3][gplv3]. - -See the [LICENSE][license] file that accompanies this distribution for the full text of the license. - -[gplv3]: http://www.gnu.org/licenses/gpl.html -[license]: https://github.com/vmihalachi/turbo-editor/LICENSE -[donate]: https://github.com/vmihalachi/turbo-editor#donate -[donate paypal]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PUQXSX6MTXHZ2 -[xda thread]: http://forum.xda-developers.com/android/apps-games/app-turbo-editor-text-editor-t2832016 -[community googleplus]: https://plus.google.com/u/0/communities/111974095419108178946 -[crowdin]: https://crowdin.net/project/turbo-client -[developer site]: http://vmihalachi.com/ -[crowdin]: https://crowdin.net/project/turbo-client -[contributor dumitru grubii]: https://twitter.com/DumitruGrubii -[project issues]: https://github.com/vmihalachi/turbo-editor/issues -[project wiki]: https://github.com/vmihalachi/turbo-editor/wiki +# Turbo Editor +[![Crowdin](https://d322cqt584bo4o.cloudfront.net/turbo-client/localized.png)](https://crowdin.com/project/turbo-client) + +Simple, powerful and Open Source text editor for Android licensed under the GPLv3 license. + +### Download +[![Play Store](http://developer.android.com/images/brand/en_generic_rgb_wo_60.png)](http://play.google.com/store/apps/details?id=com.maskyn.fileeditorpro) + +[![F-Droid](https://lh5.googleusercontent.com/-zezQqsBye0c/VCUpPVjcKEI/AAAAAAAAAIQ/HbcG5f1qMIw/w129-h45-no/getitonfdroid.png)](https://f-droid.org/repository/browse/?fdid=com.maskyn.fileeditorpro) + +### Contribute +You can contribute to this project in many ways: +* Browse our issues, comment on proposals, report bugs. +* Help to translate the application on [Crowdin][crowdin] +* Be a part of the Google Plus [Community][community googleplus] +* Discuss with us on [XDA thread][xda thread] +* Help to maintain this project active and [Donate][donate] + +------ + +###Donate +[![Paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=26VWS2TSAMUJA) + +[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=vmihalachi&url=https://github.com/vmihalachi/turbo-editor&title=Turbo Editor&language=java&tags=github&category=software) + +------ + +###Images +![](https://lh3.googleusercontent.com/-0GHukwGQPW4/VCUpEhKnZCI/AAAAAAAAAH4/cclI70K79_Q/w347-h520-no/PhoneCustom_7.png)![](https://lh3.googleusercontent.com/-OvazluFl_QQ/VCUo9DAje9I/AAAAAAAAAHQ/i7n1uCpU1hE/w347-h520-no/PhoneCustom_1.png)![](https://lh4.googleusercontent.com/-zh4CYdQPecg/VCUpD3QXpAI/AAAAAAAAAHw/ulL5-V0iJUw/w347-h520-no/PhoneCustom_6.png)![](https://lh4.googleusercontent.com/-LT3k4z9JHo8/VCUo_0jnZRI/AAAAAAAAAHg/Npk9UlkXIV8/w347-h520-no/PhoneCustom_4.png)![](https://lh5.googleusercontent.com/-hXvsf-WYvBs/VCUo9sYfR-I/AAAAAAAAAHY/TTfAgiV_7ko/w347-h520-no/PhoneCustom_3.png)![](https://lh6.googleusercontent.com/-Qib82pK6mZU/VCUpAgYmUdI/AAAAAAAAAHo/zoPVmwcatbQ/w347-h520-no/PhoneCustom_5.png)![](https://lh5.googleusercontent.com/-SERL7X-JHuc/VCax0QSlCGI/AAAAAAAAAJA/hu8dvbvJGBM/w375-h563-no/PhoneCustom_2.png) +------ + +### Developer +[Vlad Mihalachi][developer site] + +------ + +### A special thanks to.. +* [Dumitru Grubii][contributor dumitru grubii] for the icon +* All the translators +* You? + +------ + +### License +Turbo Client is made available under the terms of the [GPLv3][gplv3]. + +See the [LICENSE][license] file that accompanies this distribution for the full text of the license. + +[gplv3]: http://www.gnu.org/licenses/gpl.html +[license]: https://github.com/vmihalachi/turbo-editor/LICENSE +[donate]: https://github.com/vmihalachi/turbo-editor#donate +[donate paypal]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PUQXSX6MTXHZ2 +[xda thread]: http://forum.xda-developers.com/android/apps-games/app-turbo-editor-text-editor-t2832016 +[community googleplus]: https://plus.google.com/u/0/communities/111974095419108178946 +[crowdin]: https://crowdin.net/project/turbo-client +[developer site]: http://vmihalachi.com/ +[crowdin]: https://crowdin.net/project/turbo-client +[contributor dumitru grubii]: https://twitter.com/DumitruGrubii +[project issues]: https://github.com/vmihalachi/turbo-editor/issues +[project wiki]: https://github.com/vmihalachi/turbo-editor/wiki diff --git a/app-pro/.gitignore b/app-pro/.gitignore index 796b96d..3543521 100644 --- a/app-pro/.gitignore +++ b/app-pro/.gitignore @@ -1 +1 @@ -/build +/build diff --git a/app-pro/build.gradle b/app-pro/build.gradle index 215d6a5..7c72321 100644 --- a/app-pro/build.gradle +++ b/app-pro/build.gradle @@ -1,56 +1,55 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -apply plugin: 'com.android.application' - -android { - compileSdkVersion 21 - buildToolsVersion '21.0.2' - - defaultConfig { - applicationId "com.maskyn.fileeditorpro" - minSdkVersion 11 - targetSdkVersion 21 - versionCode 35 - versionName "1.13.2" - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - buildTypes { - release { - runProguard false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } - packagingOptions { - exclude 'META-INF/LICENSE.txt' - exclude 'META-INF/NOTICE.txt' - } -} - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile project(':libraries:sharedCode') -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +apply plugin: 'com.android.application' + +android { + compileSdkVersion 21 + buildToolsVersion '21.0.2' + + defaultConfig { + applicationId "com.maskyn.fileeditorpro" + minSdkVersion 11 + targetSdkVersion 21 + versionCode 35 + versionName "1.13.2" + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + buildTypes { + release { + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + lintOptions { + abortOnError false + } + packagingOptions { + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/NOTICE.txt' + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile project(':libraries:sharedCode') +} diff --git a/app-pro/proguard-rules.pro b/app-pro/proguard-rules.pro index 9f604d1..a946ab9 100644 --- a/app-pro/proguard-rules.pro +++ b/app-pro/proguard-rules.pro @@ -1,17 +1,17 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in C:/Users/Vlad/AppData/Local/Android/android-sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# 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 *; -#} +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:/Users/Vlad/AppData/Local/Android/android-sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# 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 *; +#} diff --git a/app-pro/src/androidTest/java/com/maskyn/fileeditorpro/ApplicationTest.java b/app-pro/src/androidTest/java/com/maskyn/fileeditorpro/ApplicationTest.java index e85c652..aba8314 100644 --- a/app-pro/src/androidTest/java/com/maskyn/fileeditorpro/ApplicationTest.java +++ b/app-pro/src/androidTest/java/com/maskyn/fileeditorpro/ApplicationTest.java @@ -1,32 +1,32 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package com.maskyn.fileeditorpro; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package com.maskyn.fileeditorpro; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } } \ No newline at end of file diff --git a/app-pro/src/main/AndroidManifest.xml b/app-pro/src/main/AndroidManifest.xml index 5d385cf..68761ef 100644 --- a/app-pro/src/main/AndroidManifest.xml +++ b/app-pro/src/main/AndroidManifest.xml @@ -1,120 +1,120 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app-pro/src/main/java/com/maskyn/fileeditorpro/HomeActivity.java b/app-pro/src/main/java/com/maskyn/fileeditorpro/HomeActivity.java index 6a80ed7..2836ac7 100644 --- a/app-pro/src/main/java/com/maskyn/fileeditorpro/HomeActivity.java +++ b/app-pro/src/main/java/com/maskyn/fileeditorpro/HomeActivity.java @@ -1,30 +1,31 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package com.maskyn.fileeditorpro; - -import sharedcode.turboeditor.activity.MainActivity; - -public class HomeActivity extends MainActivity { - - @Override - public void displayInterstitial() { - // nothing to do here - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package com.maskyn.fileeditorpro; + +import sharedcode.turboeditor.activity.MainActivity; + +public class HomeActivity extends MainActivity { + + @Override + public boolean showInterstitial() { + // nothing to do here + return false; + } +} diff --git a/app/.gitignore b/app/.gitignore index 796b96d..3543521 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1 +1 @@ -/build +/build diff --git a/app/build.gradle b/app/build.gradle index e4bf000..a7af312 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,78 +1,77 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -buildscript { - repositories { - mavenCentral() - maven { url 'https://maven.fabric.io/repo' } - } - - dependencies { - classpath 'io.fabric.tools:gradle:1.+' - } - -} - -apply plugin: 'com.android.application' -apply plugin: 'io.fabric' - -repositories { - mavenCentral() - maven { url 'https://maven.fabric.io/repo' } -} - - - -android { - compileSdkVersion 21 - buildToolsVersion '21.0.2' - defaultConfig { - applicationId "com.maskyn.fileeditor" - minSdkVersion 11 - targetSdkVersion 21 - versionCode 35 - versionName "1.13.2" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - buildTypes { - release { - runProguard false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } - packagingOptions { - exclude 'META-INF/LICENSE.txt' - exclude 'META-INF/NOTICE.txt' - } -} - -dependencies { - compile fileTree(dir: 'libs', include: '*.jar') - compile project(':libraries:sharedCode') - compile 'com.google.android.gms:play-services:6.1.11' - compile('com.crashlytics.sdk.android:crashlytics:2.+@aar') { - transitive = true; - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +buildscript { + repositories { + mavenCentral() + maven { url 'https://maven.fabric.io/repo' } + } + + dependencies { + classpath 'io.fabric.tools:gradle:1.+' + } + +} + +apply plugin: 'com.android.application' +apply plugin: 'io.fabric' + +repositories { + mavenCentral() + maven { url 'https://maven.fabric.io/repo' } +} + + + +android { + compileSdkVersion 21 + buildToolsVersion '21.0.2' + defaultConfig { + applicationId "com.maskyn.fileeditor" + minSdkVersion 11 + targetSdkVersion 21 + versionCode 35 + versionName "1.13.2" + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + buildTypes { + release { + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + lintOptions { + abortOnError false + } + packagingOptions { + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/NOTICE.txt' + } +} + +dependencies { + compile fileTree(dir: 'libs', include: '*.jar') + compile project(':libraries:sharedCode') + compile 'com.google.android.gms:play-services:6.1.11' + compile('com.crashlytics.sdk.android:crashlytics:2.+@aar') { + transitive = true; + } +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 9e22422..f65387a 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,17 +1,17 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in C:\Users\Vlad\AppData\Local\Android\android-sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# 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 *; -#} +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\Users\Vlad\AppData\Local\Android\android-sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# 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 *; +#} diff --git a/app/src/androidTest/java/com/vmihalachi/fileeditor/ApplicationTest.java b/app/src/androidTest/java/com/vmihalachi/fileeditor/ApplicationTest.java index 0ee29b9..689f300 100644 --- a/app/src/androidTest/java/com/vmihalachi/fileeditor/ApplicationTest.java +++ b/app/src/androidTest/java/com/vmihalachi/fileeditor/ApplicationTest.java @@ -1,32 +1,32 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package com.maskyn.fileeditor; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package com.maskyn.fileeditor; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2eef55b..53f483c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,129 +1,129 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/maskyn/fileeditor/AdsHelper.java b/app/src/main/java/com/maskyn/fileeditor/AdsHelper.java index 0cf91c2..c848d74 100644 --- a/app/src/main/java/com/maskyn/fileeditor/AdsHelper.java +++ b/app/src/main/java/com/maskyn/fileeditor/AdsHelper.java @@ -1,50 +1,45 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package com.maskyn.fileeditor; - -import android.app.Activity; -import android.preference.PreferenceManager; - -import com.google.android.gms.ads.AdRequest; -import com.google.android.gms.ads.InterstitialAd; - -import java.util.Calendar; - -import sharedcode.turboeditor.preferences.PreferenceHelper; - -public class AdsHelper { - private InterstitialAd interstitial; - - public AdsHelper(Activity activity) { - - interstitial = new InterstitialAd(activity); - interstitial.setAdUnitId("ca-app-pub-5679083452234719/7178038180"); - - // Create ad request. - AdRequest adRequest = new AdRequest.Builder().build(); - - // Begin loading your interstitial. - interstitial.loadAd(adRequest); - } - - public void displayInterstitial() { - interstitial.show(); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package com.maskyn.fileeditor; + +import android.app.Activity; + +import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.InterstitialAd; + +public class AdsHelper { + private InterstitialAd interstitial; + + public AdsHelper(Activity activity) { + + interstitial = new InterstitialAd(activity); + interstitial.setAdUnitId("ca-app-pub-5679083452234719/7178038180"); + + // Create ad request. + AdRequest adRequest = new AdRequest.Builder().build(); + + // Begin loading your interstitial. + interstitial.loadAd(adRequest); + } + + public void displayInterstitial() { + interstitial.show(); + } +} diff --git a/app/src/main/java/com/maskyn/fileeditor/HomeActivity.java b/app/src/main/java/com/maskyn/fileeditor/HomeActivity.java index 660f3d6..a0ff52e 100644 --- a/app/src/main/java/com/maskyn/fileeditor/HomeActivity.java +++ b/app/src/main/java/com/maskyn/fileeditor/HomeActivity.java @@ -1,51 +1,56 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package com.maskyn.fileeditor; - -import android.os.Bundle; - -import com.crashlytics.android.Crashlytics; - -import io.fabric.sdk.android.Fabric; -import sharedcode.turboeditor.activity.MainActivity; -import sharedcode.turboeditor.preferences.PreferenceHelper; -import sharedcode.turboeditor.util.ProCheckUtils; - -public class HomeActivity extends MainActivity { - - private AdsHelper adsHelper; - - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if(PreferenceHelper.getSendErrorReports(this)) - Fabric.with(this, new Crashlytics()); - // setup the ads - if(!ProCheckUtils.isPro(this)) - adsHelper = new AdsHelper(this); - } - - @Override - public void displayInterstitial() { - if(adsHelper != null && !ProCheckUtils.isPro(this)) - adsHelper.displayInterstitial(); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package com.maskyn.fileeditor; + +import android.os.Bundle; + +import com.crashlytics.android.Crashlytics; + +import io.fabric.sdk.android.Fabric; +import sharedcode.turboeditor.activity.MainActivity; + +public class HomeActivity extends MainActivity { + + private AdsHelper adsHelper; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(sharedcode.turboeditor.preferences.PreferenceHelper.getSendErrorReports(this)) + Fabric.with(this, new Crashlytics()); + // setup the ads + if(!sharedcode.turboeditor.util.ProCheckUtils.isPro(this)) + adsHelper = new AdsHelper(this); + } + + @Override + public boolean showInterstitial() { + if(adsHelper != null && !sharedcode.turboeditor.util.ProCheckUtils.isPro(this)) { + adsHelper.displayInterstitial(); + return true; + } + else { + return false; + } + } + + +} diff --git a/build.gradle b/build.gradle index 79ad207..b18ba7d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,38 +1,38 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:0.13.+' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:+' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/build/intermediates/dex-cache/cache.xml b/build/intermediates/dex-cache/cache.xml index 5db681f..bf62108 100644 --- a/build/intermediates/dex-cache/cache.xml +++ b/build/intermediates/dex-cache/cache.xml @@ -1,287 +1,96 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/intermediates/model_data.bin b/build/intermediates/model_data.bin index 83aca2f..da77581 100644 Binary files a/build/intermediates/model_data.bin and b/build/intermediates/model_data.bin differ diff --git a/gradle.properties b/gradle.properties index 79a6388..5054f97 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,37 +1,37 @@ -# -# Copyright (C) 2014 Vlad Mihalachi -# -# This file is part of Turbo Editor. -# -# Turbo Editor 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. -# -# Turbo Editor 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 . -# - -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Settings specified in this file will override any Gradle settings -# configured through the IDE. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# +# Copyright (C) 2014 Vlad Mihalachi +# +# This file is part of Turbo Editor. +# +# Turbo Editor 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. +# +# Turbo Editor 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 . +# + +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Settings specified in this file will override any Gradle settings +# configured through the IDE. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0b8241e..3f7e27a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Oct 22 18:10:25 CEST 2014 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip +#Wed Oct 22 18:10:25 CEST 2014 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip diff --git a/gradlew b/gradlew index 91a7e26..583ae08 100644 --- a/gradlew +++ b/gradlew @@ -1,164 +1,164 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat index 8a0b282..aec9973 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,90 +1,90 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/libraries/FloatingActionButton/build/generated/source/r/debug/com/faizmalkani/floatingactionbutton/R.java b/libraries/FloatingActionButton/build/generated/source/r/debug/com/faizmalkani/floatingactionbutton/R.java index 4d9193b..08a7328 100644 --- a/libraries/FloatingActionButton/build/generated/source/r/debug/com/faizmalkani/floatingactionbutton/R.java +++ b/libraries/FloatingActionButton/build/generated/source/r/debug/com/faizmalkani/floatingactionbutton/R.java @@ -1,173 +1,173 @@ -/* 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 com.faizmalkani.floatingactionbutton; - -public final class R { - public static final class attr { - /**

Must be a color value, in the form of "#rgb", "#argb", -"#rrggbb", or "#aarrggbb". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int colour=0x7f010001; - /**

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int drawable=0x7f010000; - /**

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int shadowColor=0x7f010005; - /**

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int shadowDx=0x7f010003; - /**

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int shadowDy=0x7f010004; - /**

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int shadowRadius=0x7f010002; - } - public static final class styleable { - /** Attributes that can be used with a FloatingActionButton. -

Includes the following attributes:

- - - - - - - - - - -
AttributeDescription
{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton:colour}
{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton:drawable}
{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton:shadowColor}
{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton:shadowDx}
{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton:shadowDy}
{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton:shadowRadius}
- @see #FloatingActionButton_colour - @see #FloatingActionButton_drawable - @see #FloatingActionButton_shadowColor - @see #FloatingActionButton_shadowDx - @see #FloatingActionButton_shadowDy - @see #FloatingActionButton_shadowRadius - */ - public static final int[] FloatingActionButton = { - 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, - 0x7f010004, 0x7f010005 - }; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#colour} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a color value, in the form of "#rgb", "#argb", -"#rrggbb", or "#aarrggbb". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:colour - */ - public static int FloatingActionButton_colour = 1; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#drawable} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:drawable - */ - public static int FloatingActionButton_drawable = 0; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowColor} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:shadowColor - */ - public static int FloatingActionButton_shadowColor = 5; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDx} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:shadowDx - */ - public static int FloatingActionButton_shadowDx = 3; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDy} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:shadowDy - */ - public static int FloatingActionButton_shadowDy = 4; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowRadius} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:shadowRadius - */ - public static int FloatingActionButton_shadowRadius = 2; - }; -} +/* 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 com.faizmalkani.floatingactionbutton; + +public final class R { + public static final class attr { + /**

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int colour=0x7f010001; + /**

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int drawable=0x7f010000; + /**

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int shadowColor=0x7f010005; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int shadowDx=0x7f010003; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int shadowDy=0x7f010004; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int shadowRadius=0x7f010002; + } + public static final class styleable { + /** Attributes that can be used with a FloatingActionButton. +

Includes the following attributes:

+ + + + + + + + + + +
AttributeDescription
{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton:colour}
{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton:drawable}
{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton:shadowColor}
{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton:shadowDx}
{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton:shadowDy}
{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton:shadowRadius}
+ @see #FloatingActionButton_colour + @see #FloatingActionButton_drawable + @see #FloatingActionButton_shadowColor + @see #FloatingActionButton_shadowDx + @see #FloatingActionButton_shadowDy + @see #FloatingActionButton_shadowRadius + */ + public static final int[] FloatingActionButton = { + 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, + 0x7f010004, 0x7f010005 + }; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#colour} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:colour + */ + public static int FloatingActionButton_colour = 1; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#drawable} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:drawable + */ + public static int FloatingActionButton_drawable = 0; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowColor} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:shadowColor + */ + public static int FloatingActionButton_shadowColor = 5; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDx} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:shadowDx + */ + public static int FloatingActionButton_shadowDx = 3; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDy} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:shadowDy + */ + public static int FloatingActionButton_shadowDy = 4; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowRadius} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:shadowRadius + */ + public static int FloatingActionButton_shadowRadius = 2; + }; +} diff --git a/libraries/FloatingActionButton/build/generated/source/r/release/com/faizmalkani/floatingactionbutton/R.java b/libraries/FloatingActionButton/build/generated/source/r/release/com/faizmalkani/floatingactionbutton/R.java index 4d9193b..08a7328 100644 --- a/libraries/FloatingActionButton/build/generated/source/r/release/com/faizmalkani/floatingactionbutton/R.java +++ b/libraries/FloatingActionButton/build/generated/source/r/release/com/faizmalkani/floatingactionbutton/R.java @@ -1,173 +1,173 @@ -/* 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 com.faizmalkani.floatingactionbutton; - -public final class R { - public static final class attr { - /**

Must be a color value, in the form of "#rgb", "#argb", -"#rrggbb", or "#aarrggbb". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int colour=0x7f010001; - /**

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int drawable=0x7f010000; - /**

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int shadowColor=0x7f010005; - /**

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int shadowDx=0x7f010003; - /**

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int shadowDy=0x7f010004; - /**

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static int shadowRadius=0x7f010002; - } - public static final class styleable { - /** Attributes that can be used with a FloatingActionButton. -

Includes the following attributes:

- - - - - - - - - - -
AttributeDescription
{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton:colour}
{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton:drawable}
{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton:shadowColor}
{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton:shadowDx}
{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton:shadowDy}
{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton:shadowRadius}
- @see #FloatingActionButton_colour - @see #FloatingActionButton_drawable - @see #FloatingActionButton_shadowColor - @see #FloatingActionButton_shadowDx - @see #FloatingActionButton_shadowDy - @see #FloatingActionButton_shadowRadius - */ - public static final int[] FloatingActionButton = { - 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, - 0x7f010004, 0x7f010005 - }; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#colour} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a color value, in the form of "#rgb", "#argb", -"#rrggbb", or "#aarrggbb". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:colour - */ - public static int FloatingActionButton_colour = 1; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#drawable} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:drawable - */ - public static int FloatingActionButton_drawable = 0; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowColor} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:shadowColor - */ - public static int FloatingActionButton_shadowColor = 5; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDx} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:shadowDx - */ - public static int FloatingActionButton_shadowDx = 3; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDy} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:shadowDy - */ - public static int FloatingActionButton_shadowDy = 4; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowRadius} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton:shadowRadius - */ - public static int FloatingActionButton_shadowRadius = 2; - }; -} +/* 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 com.faizmalkani.floatingactionbutton; + +public final class R { + public static final class attr { + /**

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int colour=0x7f010001; + /**

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int drawable=0x7f010000; + /**

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int shadowColor=0x7f010005; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int shadowDx=0x7f010003; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int shadowDy=0x7f010004; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int shadowRadius=0x7f010002; + } + public static final class styleable { + /** Attributes that can be used with a FloatingActionButton. +

Includes the following attributes:

+ + + + + + + + + + +
AttributeDescription
{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton:colour}
{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton:drawable}
{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton:shadowColor}
{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton:shadowDx}
{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton:shadowDy}
{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton:shadowRadius}
+ @see #FloatingActionButton_colour + @see #FloatingActionButton_drawable + @see #FloatingActionButton_shadowColor + @see #FloatingActionButton_shadowDx + @see #FloatingActionButton_shadowDy + @see #FloatingActionButton_shadowRadius + */ + public static final int[] FloatingActionButton = { + 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, + 0x7f010004, 0x7f010005 + }; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#colour} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:colour + */ + public static int FloatingActionButton_colour = 1; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#drawable} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:drawable + */ + public static int FloatingActionButton_drawable = 0; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowColor} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:shadowColor + */ + public static int FloatingActionButton_shadowColor = 5; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDx} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:shadowDx + */ + public static int FloatingActionButton_shadowDx = 3; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDy} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:shadowDy + */ + public static int FloatingActionButton_shadowDy = 4; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowRadius} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton:shadowRadius + */ + public static int FloatingActionButton_shadowRadius = 2; + }; +} diff --git a/libraries/FloatingActionButton/build/generated/source/r/test/debug/com/faizmalkani/floatingactionbutton/test/R.java b/libraries/FloatingActionButton/build/generated/source/r/test/debug/com/faizmalkani/floatingactionbutton/test/R.java index c2a3510..fb8b605 100644 --- a/libraries/FloatingActionButton/build/generated/source/r/test/debug/com/faizmalkani/floatingactionbutton/test/R.java +++ b/libraries/FloatingActionButton/build/generated/source/r/test/debug/com/faizmalkani/floatingactionbutton/test/R.java @@ -1,173 +1,173 @@ -/* 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 com.faizmalkani.floatingactionbutton.test; - -public final class R { - public static final class attr { - /**

Must be a color value, in the form of "#rgb", "#argb", -"#rrggbb", or "#aarrggbb". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static final int colour=0x7f010001; - /**

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static final int drawable=0x7f010000; - /**

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static final int shadowColor=0x7f010005; - /**

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static final int shadowDx=0x7f010003; - /**

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static final int shadowDy=0x7f010004; - /**

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - */ - public static final int shadowRadius=0x7f010002; - } - public static final class styleable { - /** Attributes that can be used with a FloatingActionButton. -

Includes the following attributes:

- - - - - - - - - - -
AttributeDescription
{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton.test:colour}
{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton.test:drawable}
{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton.test:shadowColor}
{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton.test:shadowDx}
{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton.test:shadowDy}
{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton.test:shadowRadius}
- @see #FloatingActionButton_colour - @see #FloatingActionButton_drawable - @see #FloatingActionButton_shadowColor - @see #FloatingActionButton_shadowDx - @see #FloatingActionButton_shadowDy - @see #FloatingActionButton_shadowRadius - */ - public static final int[] FloatingActionButton = { - 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, - 0x7f010004, 0x7f010005 - }; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#colour} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a color value, in the form of "#rgb", "#argb", -"#rrggbb", or "#aarrggbb". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton.test:colour - */ - public static final int FloatingActionButton_colour = 1; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#drawable} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton.test:drawable - */ - public static final int FloatingActionButton_drawable = 0; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowColor} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be an integer value, such as "100". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton.test:shadowColor - */ - public static final int FloatingActionButton_shadowColor = 5; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowDx} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton.test:shadowDx - */ - public static final int FloatingActionButton_shadowDx = 3; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowDy} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton.test:shadowDy - */ - public static final int FloatingActionButton_shadowDy = 4; - /** -

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowRadius} - attribute's value can be found in the {@link #FloatingActionButton} array. - - -

Must be a floating point value, such as "1.2". -

This may also be a reference to a resource (in the form -"@[package:]type:name") or -theme attribute (in the form -"?[package:][type:]name") -containing a value of this type. - @attr name com.faizmalkani.floatingactionbutton.test:shadowRadius - */ - public static final int FloatingActionButton_shadowRadius = 2; - }; -} +/* 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 com.faizmalkani.floatingactionbutton.test; + +public final class R { + public static final class attr { + /**

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int colour=0x7f010001; + /**

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int drawable=0x7f010000; + /**

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int shadowColor=0x7f010005; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int shadowDx=0x7f010003; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int shadowDy=0x7f010004; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int shadowRadius=0x7f010002; + } + public static final class styleable { + /** Attributes that can be used with a FloatingActionButton. +

Includes the following attributes:

+ + + + + + + + + + +
AttributeDescription
{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton.test:colour}
{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton.test:drawable}
{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton.test:shadowColor}
{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton.test:shadowDx}
{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton.test:shadowDy}
{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton.test:shadowRadius}
+ @see #FloatingActionButton_colour + @see #FloatingActionButton_drawable + @see #FloatingActionButton_shadowColor + @see #FloatingActionButton_shadowDx + @see #FloatingActionButton_shadowDy + @see #FloatingActionButton_shadowRadius + */ + public static final int[] FloatingActionButton = { + 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, + 0x7f010004, 0x7f010005 + }; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#colour} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:colour + */ + public static final int FloatingActionButton_colour = 1; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#drawable} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:drawable + */ + public static final int FloatingActionButton_drawable = 0; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowColor} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:shadowColor + */ + public static final int FloatingActionButton_shadowColor = 5; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowDx} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:shadowDx + */ + public static final int FloatingActionButton_shadowDx = 3; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowDy} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:shadowDy + */ + public static final int FloatingActionButton_shadowDy = 4; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowRadius} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:shadowRadius + */ + public static final int FloatingActionButton_shadowRadius = 2; + }; +} diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/debug/AndroidManifest.xml b/libraries/FloatingActionButton/build/intermediates/bundles/debug/AndroidManifest.xml index 28dac35..77c4652 100644 --- a/libraries/FloatingActionButton/build/intermediates/bundles/debug/AndroidManifest.xml +++ b/libraries/FloatingActionButton/build/intermediates/bundles/debug/AndroidManifest.xml @@ -1,14 +1,14 @@ - - - - - - - + + + + + + + \ No newline at end of file diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/debug/R.txt b/libraries/FloatingActionButton/build/intermediates/bundles/debug/R.txt index a11b389..41bb8b7 100644 --- a/libraries/FloatingActionButton/build/intermediates/bundles/debug/R.txt +++ b/libraries/FloatingActionButton/build/intermediates/bundles/debug/R.txt @@ -1,13 +1,13 @@ -int attr colour 0x7f010001 -int attr drawable 0x7f010000 -int attr shadowColor 0x7f010005 -int attr shadowDx 0x7f010003 -int attr shadowDy 0x7f010004 -int attr shadowRadius 0x7f010002 -int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 } -int styleable FloatingActionButton_colour 1 -int styleable FloatingActionButton_drawable 0 -int styleable FloatingActionButton_shadowColor 5 -int styleable FloatingActionButton_shadowDx 3 -int styleable FloatingActionButton_shadowDy 4 -int styleable FloatingActionButton_shadowRadius 2 +int attr colour 0x7f010001 +int attr drawable 0x7f010000 +int attr shadowColor 0x7f010005 +int attr shadowDx 0x7f010003 +int attr shadowDy 0x7f010004 +int attr shadowRadius 0x7f010002 +int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 } +int styleable FloatingActionButton_colour 1 +int styleable FloatingActionButton_drawable 0 +int styleable FloatingActionButton_shadowColor 5 +int styleable FloatingActionButton_shadowDx 3 +int styleable FloatingActionButton_shadowDy 4 +int styleable FloatingActionButton_shadowRadius 2 diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/debug/classes.jar b/libraries/FloatingActionButton/build/intermediates/bundles/debug/classes.jar index 34fee55..c028b84 100644 Binary files a/libraries/FloatingActionButton/build/intermediates/bundles/debug/classes.jar and b/libraries/FloatingActionButton/build/intermediates/bundles/debug/classes.jar differ diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/release/AndroidManifest.xml b/libraries/FloatingActionButton/build/intermediates/bundles/release/AndroidManifest.xml index 28dac35..77c4652 100644 --- a/libraries/FloatingActionButton/build/intermediates/bundles/release/AndroidManifest.xml +++ b/libraries/FloatingActionButton/build/intermediates/bundles/release/AndroidManifest.xml @@ -1,14 +1,14 @@ - - - - - - - + + + + + + + \ No newline at end of file diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/release/R.txt b/libraries/FloatingActionButton/build/intermediates/bundles/release/R.txt index a11b389..41bb8b7 100644 --- a/libraries/FloatingActionButton/build/intermediates/bundles/release/R.txt +++ b/libraries/FloatingActionButton/build/intermediates/bundles/release/R.txt @@ -1,13 +1,13 @@ -int attr colour 0x7f010001 -int attr drawable 0x7f010000 -int attr shadowColor 0x7f010005 -int attr shadowDx 0x7f010003 -int attr shadowDy 0x7f010004 -int attr shadowRadius 0x7f010002 -int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 } -int styleable FloatingActionButton_colour 1 -int styleable FloatingActionButton_drawable 0 -int styleable FloatingActionButton_shadowColor 5 -int styleable FloatingActionButton_shadowDx 3 -int styleable FloatingActionButton_shadowDy 4 -int styleable FloatingActionButton_shadowRadius 2 +int attr colour 0x7f010001 +int attr drawable 0x7f010000 +int attr shadowColor 0x7f010005 +int attr shadowDx 0x7f010003 +int attr shadowDy 0x7f010004 +int attr shadowRadius 0x7f010002 +int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 } +int styleable FloatingActionButton_colour 1 +int styleable FloatingActionButton_drawable 0 +int styleable FloatingActionButton_shadowColor 5 +int styleable FloatingActionButton_shadowDx 3 +int styleable FloatingActionButton_shadowDy 4 +int styleable FloatingActionButton_shadowRadius 2 diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/release/classes.jar b/libraries/FloatingActionButton/build/intermediates/bundles/release/classes.jar index 1056848..3648093 100644 Binary files a/libraries/FloatingActionButton/build/intermediates/bundles/release/classes.jar and b/libraries/FloatingActionButton/build/intermediates/bundles/release/classes.jar differ diff --git a/libraries/FloatingActionButton/build/intermediates/manifests/test/debug/AndroidManifest.xml b/libraries/FloatingActionButton/build/intermediates/manifests/test/debug/AndroidManifest.xml index fb4c5e3..d057938 100644 --- a/libraries/FloatingActionButton/build/intermediates/manifests/test/debug/AndroidManifest.xml +++ b/libraries/FloatingActionButton/build/intermediates/manifests/test/debug/AndroidManifest.xml @@ -1,20 +1,20 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger1672337899454975879.xml b/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger7569492401838877170.xml similarity index 100% rename from libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger1672337899454975879.xml rename to libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger7569492401838877170.xml diff --git a/libraries/FloatingActionButton/build/intermediates/symbols/test/debug/R.txt b/libraries/FloatingActionButton/build/intermediates/symbols/test/debug/R.txt index a11b389..41bb8b7 100644 --- a/libraries/FloatingActionButton/build/intermediates/symbols/test/debug/R.txt +++ b/libraries/FloatingActionButton/build/intermediates/symbols/test/debug/R.txt @@ -1,13 +1,13 @@ -int attr colour 0x7f010001 -int attr drawable 0x7f010000 -int attr shadowColor 0x7f010005 -int attr shadowDx 0x7f010003 -int attr shadowDy 0x7f010004 -int attr shadowRadius 0x7f010002 -int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 } -int styleable FloatingActionButton_colour 1 -int styleable FloatingActionButton_drawable 0 -int styleable FloatingActionButton_shadowColor 5 -int styleable FloatingActionButton_shadowDx 3 -int styleable FloatingActionButton_shadowDy 4 -int styleable FloatingActionButton_shadowRadius 2 +int attr colour 0x7f010001 +int attr drawable 0x7f010000 +int attr shadowColor 0x7f010005 +int attr shadowDx 0x7f010003 +int attr shadowDy 0x7f010004 +int attr shadowRadius 0x7f010002 +int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 } +int styleable FloatingActionButton_colour 1 +int styleable FloatingActionButton_drawable 0 +int styleable FloatingActionButton_shadowColor 5 +int styleable FloatingActionButton_shadowDx 3 +int styleable FloatingActionButton_shadowDy 4 +int styleable FloatingActionButton_shadowRadius 2 diff --git a/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-debug.aar b/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-debug.aar index b42693c..61d4432 100644 Binary files a/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-debug.aar and b/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-debug.aar differ diff --git a/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-release.aar b/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-release.aar index 6c0433b..7f50b23 100644 Binary files a/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-release.aar and b/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-release.aar differ diff --git a/libraries/FloatingActionButton/build/tmp/packageDebugJar/MANIFEST.MF b/libraries/FloatingActionButton/build/tmp/packageDebugJar/MANIFEST.MF index 59499bc..58630c0 100644 --- a/libraries/FloatingActionButton/build/tmp/packageDebugJar/MANIFEST.MF +++ b/libraries/FloatingActionButton/build/tmp/packageDebugJar/MANIFEST.MF @@ -1,2 +1,2 @@ -Manifest-Version: 1.0 - +Manifest-Version: 1.0 + diff --git a/libraries/FloatingActionButton/build/tmp/packageReleaseJar/MANIFEST.MF b/libraries/FloatingActionButton/build/tmp/packageReleaseJar/MANIFEST.MF index 59499bc..58630c0 100644 --- a/libraries/FloatingActionButton/build/tmp/packageReleaseJar/MANIFEST.MF +++ b/libraries/FloatingActionButton/build/tmp/packageReleaseJar/MANIFEST.MF @@ -1,2 +1,2 @@ -Manifest-Version: 1.0 - +Manifest-Version: 1.0 + diff --git a/libraries/RootCommands/.gitignore b/libraries/RootCommands/.gitignore index afa9dfc..ef0916c 100644 --- a/libraries/RootCommands/.gitignore +++ b/libraries/RootCommands/.gitignore @@ -1,33 +1,33 @@ -#Android specific -bin -gen -obj -libs/armeabi -lint.xml -local.properties -release.properties -ant.properties -*.class -*.apk - -#Gradle -.gradle -build -gradle.properties -gradlew -gradlew.bat -gradle - -#Maven -target -pom.xml.* - -#Eclipse -.project -.classpath -.settings -.metadata - -#IntelliJ IDEA -.idea -*.iml +#Android specific +bin +gen +obj +libs/armeabi +lint.xml +local.properties +release.properties +ant.properties +*.class +*.apk + +#Gradle +.gradle +build +gradle.properties +gradlew +gradlew.bat +gradle + +#Maven +target +pom.xml.* + +#Eclipse +.project +.classpath +.settings +.metadata + +#IntelliJ IDEA +.idea +*.iml diff --git a/libraries/RootCommands/build.gradle b/libraries/RootCommands/build.gradle index e13b766..7165c64 100644 --- a/libraries/RootCommands/build.gradle +++ b/libraries/RootCommands/build.gradle @@ -1,30 +1,30 @@ - - -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:0.12.+' - } -} - -apply plugin: 'com.android.library' - -dependencies { -} - -android { - compileSdkVersion 21 - buildToolsVersion '21.0.2' - - defaultConfig { - minSdkVersion 7 - targetSdkVersion 21 - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } -} - + + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:0.12.+' + } +} + +apply plugin: 'com.android.library' + +dependencies { +} + +android { + compileSdkVersion 21 + buildToolsVersion '21.0.2' + + defaultConfig { + minSdkVersion 7 + targetSdkVersion 21 + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } +} + diff --git a/libraries/RootCommands/src/main/AndroidManifest.xml b/libraries/RootCommands/src/main/AndroidManifest.xml index 060f6d2..da34713 100644 --- a/libraries/RootCommands/src/main/AndroidManifest.xml +++ b/libraries/RootCommands/src/main/AndroidManifest.xml @@ -1,15 +1,15 @@ - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Mount.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Mount.java index 9062d54..d3277dd 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Mount.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Mount.java @@ -1,43 +1,43 @@ - - -package org.sufficientlysecure.rootcommands; - -import java.io.File; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -public class Mount { - protected final File mDevice; - protected final File mMountPoint; - protected final String mType; - protected final Set mFlags; - - Mount(File device, File path, String type, String flagsStr) { - mDevice = device; - mMountPoint = path; - mType = type; - mFlags = new HashSet(Arrays.asList(flagsStr.split(","))); - } - - public File getDevice() { - return mDevice; - } - - public File getMountPoint() { - return mMountPoint; - } - - public String getType() { - return mType; - } - - public Set getFlags() { - return mFlags; - } - - @Override - public String toString() { - return String.format("%s on %s type %s %s", mDevice, mMountPoint, mType, mFlags); - } -} + + +package org.sufficientlysecure.rootcommands; + +import java.io.File; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class Mount { + protected final File mDevice; + protected final File mMountPoint; + protected final String mType; + protected final Set mFlags; + + Mount(File device, File path, String type, String flagsStr) { + mDevice = device; + mMountPoint = path; + mType = type; + mFlags = new HashSet(Arrays.asList(flagsStr.split(","))); + } + + public File getDevice() { + return mDevice; + } + + public File getMountPoint() { + return mMountPoint; + } + + public String getType() { + return mType; + } + + public Set getFlags() { + return mFlags; + } + + @Override + public String toString() { + return String.format("%s on %s type %s %s", mDevice, mMountPoint, mType, mFlags); + } +} diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Remounter.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Remounter.java index 2ec1cbf..4ffa893 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Remounter.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Remounter.java @@ -1,176 +1,176 @@ - - -package org.sufficientlysecure.rootcommands; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.LineNumberReader; -import java.util.ArrayList; -import java.util.Locale; - -import org.sufficientlysecure.rootcommands.command.SimpleCommand; -import org.sufficientlysecure.rootcommands.util.Log; - -//no modifier, this means it is package-private. Only our internal classes can use this. -class Remounter { - - private Shell shell; - - public Remounter(Shell shell) { - super(); - this.shell = shell; - } - - /** - * This will take a path, which can contain the file name as well, and attempt to remount the - * underlying partition. - *

- * For example, passing in the following string: - * "/system/bin/some/directory/that/really/would/never/exist" will result in /system ultimately - * being remounted. However, keep in mind that the longer the path you supply, the more work - * this has to do, and the slower it will run. - * - * @param file - * file path - * @param mountType - * mount type: pass in RO (Read only) or RW (Read Write) - * @return a boolean which indicates whether or not the partition has been - * remounted as specified. - */ - protected boolean remount(String file, String mountType) { - - // if the path has a trailing slash get rid of it. - if (file.endsWith("/") && !file.equals("/")) { - file = file.substring(0, file.lastIndexOf("/")); - } - // Make sure that what we are trying to remount is in the mount list. - boolean foundMount = false; - while (!foundMount) { - try { - for (Mount mount : getMounts()) { - Log.d(RootCommands.TAG, mount.getMountPoint().toString()); - - if (file.equals(mount.getMountPoint().toString())) { - foundMount = true; - break; - } - } - } catch (Exception e) { - Log.e(RootCommands.TAG, "Exception", e); - return false; - } - if (!foundMount) { - try { - file = (new File(file).getParent()).toString(); - } catch (Exception e) { - Log.e(RootCommands.TAG, "Exception", e); - return false; - } - } - } - Mount mountPoint = findMountPointRecursive(file); - - Log.d(RootCommands.TAG, "Remounting " + mountPoint.getMountPoint().getAbsolutePath() - + " as " + mountType.toLowerCase(Locale.US)); - final boolean isMountMode = mountPoint.getFlags().contains(mountType.toLowerCase(Locale.US)); - - if (!isMountMode) { - // grab an instance of the internal class - try { - SimpleCommand command = new SimpleCommand("busybox mount -o remount," - + mountType.toLowerCase(Locale.US) + " " + mountPoint.getDevice().getAbsolutePath() - + " " + mountPoint.getMountPoint().getAbsolutePath(), - "toolbox mount -o remount," + mountType.toLowerCase(Locale.US) + " " - + mountPoint.getDevice().getAbsolutePath() + " " - + mountPoint.getMountPoint().getAbsolutePath(), "mount -o remount," - + mountType.toLowerCase(Locale.US) + " " - + mountPoint.getDevice().getAbsolutePath() + " " - + mountPoint.getMountPoint().getAbsolutePath(), - "/system/bin/toolbox mount -o remount," + mountType.toLowerCase(Locale.US) + " " - + mountPoint.getDevice().getAbsolutePath() + " " - + mountPoint.getMountPoint().getAbsolutePath()); - - // execute on shell - shell.add(command).waitForFinish(); - - } catch (Exception e) { - } - - mountPoint = findMountPointRecursive(file); - } - - if (mountPoint != null) { - Log.d(RootCommands.TAG, mountPoint.getFlags() + " AND " + mountType.toLowerCase(Locale.US)); - if (mountPoint.getFlags().contains(mountType.toLowerCase(Locale.US))) { - Log.d(RootCommands.TAG, mountPoint.getFlags().toString()); - return true; - } else { - Log.d(RootCommands.TAG, mountPoint.getFlags().toString()); - } - } else { - Log.d(RootCommands.TAG, "mountPoint is null"); - } - return false; - } - - private Mount findMountPointRecursive(String file) { - try { - ArrayList mounts = getMounts(); - for (File path = new File(file); path != null;) { - for (Mount mount : mounts) { - if (mount.getMountPoint().equals(path)) { - return mount; - } - } - } - return null; - } catch (IOException e) { - throw new RuntimeException(e); - } catch (Exception e) { - Log.e(RootCommands.TAG, "Exception", e); - } - return null; - } - - /** - * This will return an ArrayList of the class Mount. The class mount contains the following - * property's: device mountPoint type flags - *

- * These will provide you with any information you need to work with the mount points. - * - * @return ArrayList an ArrayList of the class Mount. - * @throws Exception - * if we cannot return the mount points. - */ - protected static ArrayList getMounts() throws Exception { - - final String tempFile = "/data/local/RootToolsMounts"; - - // copy /proc/mounts to tempfile. Directly reading it does not work on 4.3 - Shell shell = Shell.startRootShell(); - Toolbox tb = new Toolbox(shell); - tb.copyFile("/proc/mounts", tempFile, false, false); - tb.setFilePermissions(tempFile, "777"); - shell.close(); - - LineNumberReader lnr = null; - lnr = new LineNumberReader(new FileReader(tempFile)); - String line; - ArrayList mounts = new ArrayList(); - while ((line = lnr.readLine()) != null) { - - Log.d(RootCommands.TAG, line); - - String[] fields = line.split(" "); - mounts.add(new Mount(new File(fields[0]), // device - new File(fields[1]), // mountPoint - fields[2], // fstype - fields[3] // flags - )); - } - lnr.close(); - - return mounts; - } -} + + +package org.sufficientlysecure.rootcommands; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.LineNumberReader; +import java.util.ArrayList; +import java.util.Locale; + +import org.sufficientlysecure.rootcommands.command.SimpleCommand; +import org.sufficientlysecure.rootcommands.util.Log; + +//no modifier, this means it is package-private. Only our internal classes can use this. +class Remounter { + + private Shell shell; + + public Remounter(Shell shell) { + super(); + this.shell = shell; + } + + /** + * This will take a path, which can contain the file name as well, and attempt to remount the + * underlying partition. + *

+ * For example, passing in the following string: + * "/system/bin/some/directory/that/really/would/never/exist" will result in /system ultimately + * being remounted. However, keep in mind that the longer the path you supply, the more work + * this has to do, and the slower it will run. + * + * @param file + * file path + * @param mountType + * mount type: pass in RO (Read only) or RW (Read Write) + * @return a boolean which indicates whether or not the partition has been + * remounted as specified. + */ + protected boolean remount(String file, String mountType) { + + // if the path has a trailing slash get rid of it. + if (file.endsWith("/") && !file.equals("/")) { + file = file.substring(0, file.lastIndexOf("/")); + } + // Make sure that what we are trying to remount is in the mount list. + boolean foundMount = false; + while (!foundMount) { + try { + for (Mount mount : getMounts()) { + Log.d(RootCommands.TAG, mount.getMountPoint().toString()); + + if (file.equals(mount.getMountPoint().toString())) { + foundMount = true; + break; + } + } + } catch (Exception e) { + Log.e(RootCommands.TAG, "Exception", e); + return false; + } + if (!foundMount) { + try { + file = (new File(file).getParent()).toString(); + } catch (Exception e) { + Log.e(RootCommands.TAG, "Exception", e); + return false; + } + } + } + Mount mountPoint = findMountPointRecursive(file); + + Log.d(RootCommands.TAG, "Remounting " + mountPoint.getMountPoint().getAbsolutePath() + + " as " + mountType.toLowerCase(Locale.US)); + final boolean isMountMode = mountPoint.getFlags().contains(mountType.toLowerCase(Locale.US)); + + if (!isMountMode) { + // grab an instance of the internal class + try { + SimpleCommand command = new SimpleCommand("busybox mount -o remount," + + mountType.toLowerCase(Locale.US) + " " + mountPoint.getDevice().getAbsolutePath() + + " " + mountPoint.getMountPoint().getAbsolutePath(), + "toolbox mount -o remount," + mountType.toLowerCase(Locale.US) + " " + + mountPoint.getDevice().getAbsolutePath() + " " + + mountPoint.getMountPoint().getAbsolutePath(), "mount -o remount," + + mountType.toLowerCase(Locale.US) + " " + + mountPoint.getDevice().getAbsolutePath() + " " + + mountPoint.getMountPoint().getAbsolutePath(), + "/system/bin/toolbox mount -o remount," + mountType.toLowerCase(Locale.US) + " " + + mountPoint.getDevice().getAbsolutePath() + " " + + mountPoint.getMountPoint().getAbsolutePath()); + + // execute on shell + shell.add(command).waitForFinish(); + + } catch (Exception e) { + } + + mountPoint = findMountPointRecursive(file); + } + + if (mountPoint != null) { + Log.d(RootCommands.TAG, mountPoint.getFlags() + " AND " + mountType.toLowerCase(Locale.US)); + if (mountPoint.getFlags().contains(mountType.toLowerCase(Locale.US))) { + Log.d(RootCommands.TAG, mountPoint.getFlags().toString()); + return true; + } else { + Log.d(RootCommands.TAG, mountPoint.getFlags().toString()); + } + } else { + Log.d(RootCommands.TAG, "mountPoint is null"); + } + return false; + } + + private Mount findMountPointRecursive(String file) { + try { + ArrayList mounts = getMounts(); + for (File path = new File(file); path != null;) { + for (Mount mount : mounts) { + if (mount.getMountPoint().equals(path)) { + return mount; + } + } + } + return null; + } catch (IOException e) { + throw new RuntimeException(e); + } catch (Exception e) { + Log.e(RootCommands.TAG, "Exception", e); + } + return null; + } + + /** + * This will return an ArrayList of the class Mount. The class mount contains the following + * property's: device mountPoint type flags + *

+ * These will provide you with any information you need to work with the mount points. + * + * @return ArrayList an ArrayList of the class Mount. + * @throws Exception + * if we cannot return the mount points. + */ + protected static ArrayList getMounts() throws Exception { + + final String tempFile = "/data/local/RootToolsMounts"; + + // copy /proc/mounts to tempfile. Directly reading it does not work on 4.3 + Shell shell = Shell.startRootShell(); + Toolbox tb = new Toolbox(shell); + tb.copyFile("/proc/mounts", tempFile, false, false); + tb.setFilePermissions(tempFile, "777"); + shell.close(); + + LineNumberReader lnr = null; + lnr = new LineNumberReader(new FileReader(tempFile)); + String line; + ArrayList mounts = new ArrayList(); + while ((line = lnr.readLine()) != null) { + + Log.d(RootCommands.TAG, line); + + String[] fields = line.split(" "); + mounts.add(new Mount(new File(fields[0]), // device + new File(fields[1]), // mountPoint + fields[2], // fstype + fields[3] // flags + )); + } + lnr.close(); + + return mounts; + } +} diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/RootCommands.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/RootCommands.java index 50ebe18..4b12ae3 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/RootCommands.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/RootCommands.java @@ -1,36 +1,36 @@ - - -package org.sufficientlysecure.rootcommands; - -import org.sufficientlysecure.rootcommands.util.Log; - -public class RootCommands { - public static boolean DEBUG = false; - public static int DEFAULT_TIMEOUT = 10000; - - public static final String TAG = "RootCommands"; - - /** - * General method to check if user has su binary and accepts root access for this program! - * - * @return true if everything worked - */ - public static boolean rootAccessGiven() { - boolean rootAccess = false; - - try { - Shell rootShell = Shell.startRootShell(); - - Toolbox tb = new Toolbox(rootShell); - if (tb.isRootAccessGiven()) { - rootAccess = true; - } - - rootShell.close(); - } catch (Exception e) { - Log.e(TAG, "Problem while checking for root access!", e); - } - - return rootAccess; - } -} + + +package org.sufficientlysecure.rootcommands; + +import org.sufficientlysecure.rootcommands.util.Log; + +public class RootCommands { + public static boolean DEBUG = false; + public static int DEFAULT_TIMEOUT = 10000; + + public static final String TAG = "RootCommands"; + + /** + * General method to check if user has su binary and accepts root access for this program! + * + * @return true if everything worked + */ + public static boolean rootAccessGiven() { + boolean rootAccess = false; + + try { + Shell rootShell = Shell.startRootShell(); + + Toolbox tb = new Toolbox(rootShell); + if (tb.isRootAccessGiven()) { + rootAccess = true; + } + + rootShell.close(); + } catch (Exception e) { + Log.e(TAG, "Problem while checking for root access!", e); + } + + return rootAccess; + } +} diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Shell.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Shell.java index 0b749ca..b5c8ab6 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Shell.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Shell.java @@ -1,331 +1,331 @@ - - -package org.sufficientlysecure.rootcommands; - -import java.io.BufferedReader; -import java.io.Closeable; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -import org.sufficientlysecure.rootcommands.command.Command; -import org.sufficientlysecure.rootcommands.util.Log; -import org.sufficientlysecure.rootcommands.util.RootAccessDeniedException; -import org.sufficientlysecure.rootcommands.util.Utils; - -public class Shell implements Closeable { - private final Process shellProcess; - private final BufferedReader stdOutErr; - private final DataOutputStream outputStream; - private final List commands = new ArrayList(); - private boolean close = false; - - private static final String LD_LIBRARY_PATH = System.getenv("LD_LIBRARY_PATH"); - private static final String token = "F*D^W@#FGF"; - - /** - * Start root shell - * - * @param customEnv - * @param baseDirectory - * @return - * @throws java.io.IOException - */ - public static Shell startRootShell(ArrayList customEnv, String baseDirectory) - throws IOException, RootAccessDeniedException { - Log.d(RootCommands.TAG, "Starting Root Shell!"); - - // On some versions of Android (ICS) LD_LIBRARY_PATH is unset when using su - // We need to pass LD_LIBRARY_PATH over su for some commands to work correctly. - if (customEnv == null) { - customEnv = new ArrayList(); - } - customEnv.add("LD_LIBRARY_PATH=" + LD_LIBRARY_PATH); - - Shell shell = new Shell(Utils.getSuPath(), customEnv, baseDirectory); - - return shell; - } - - /** - * Start root shell without custom environment and base directory - * - * @return - * @throws java.io.IOException - */ - public static Shell startRootShell() throws IOException, RootAccessDeniedException { - return startRootShell(null, null); - } - - /** - * Start default sh shell - * - * @param customEnv - * @param baseDirectory - * @return - * @throws java.io.IOException - */ - public static Shell startShell(ArrayList customEnv, String baseDirectory) - throws IOException { - Log.d(RootCommands.TAG, "Starting Shell!"); - Shell shell = new Shell("sh", customEnv, baseDirectory); - return shell; - } - - /** - * Start default sh shell without custom environment and base directory - * - * @return - * @throws java.io.IOException - */ - public static Shell startShell() throws IOException { - return startShell(null, null); - } - - /** - * Start custom shell defined by shellPath - * - * @param shellPath - * @param customEnv - * @param baseDirectory - * @return - * @throws java.io.IOException - */ - public static Shell startCustomShell(String shellPath, ArrayList customEnv, - String baseDirectory) throws IOException { - Log.d(RootCommands.TAG, "Starting Custom Shell!"); - Shell shell = new Shell(shellPath, customEnv, baseDirectory); - - return shell; - } - - /** - * Start custom shell without custom environment and base directory - * - * @param shellPath - * @return - * @throws java.io.IOException - */ - public static Shell startCustomShell(String shellPath) throws IOException { - return startCustomShell(shellPath, null, null); - } - - private Shell(String shell, ArrayList customEnv, String baseDirectory) - throws IOException, RootAccessDeniedException { - Log.d(RootCommands.TAG, "Starting shell: " + shell); - - // start shell process! - shellProcess = Utils.runWithEnv(shell, customEnv, baseDirectory); - - // StdErr is redirected to StdOut, defined in Command.getCommand() - stdOutErr = new BufferedReader(new InputStreamReader(shellProcess.getInputStream())); - outputStream = new DataOutputStream(shellProcess.getOutputStream()); - - outputStream.write("echo Started\n".getBytes()); - outputStream.flush(); - - while (true) { - String line = stdOutErr.readLine(); - if (line == null) - throw new RootAccessDeniedException( - "stdout line is null! Access was denied or this executeable is not a shell!"); - if ("".equals(line)) - continue; - if ("Started".equals(line)) - break; - - destroyShellProcess(); - throw new IOException("Unable to start shell, unexpected output \"" + line + "\""); - } - - new Thread(inputRunnable, "Shell Input").start(); - new Thread(outputRunnable, "Shell Output").start(); - } - - private Runnable inputRunnable = new Runnable() { - public void run() { - try { - writeCommands(); - } catch (IOException e) { - Log.e(RootCommands.TAG, "IO Exception", e); - } - } - }; - - private Runnable outputRunnable = new Runnable() { - public void run() { - try { - readOutput(); - } catch (IOException e) { - Log.e(RootCommands.TAG, "IOException", e); - } catch (InterruptedException e) { - Log.e(RootCommands.TAG, "InterruptedException", e); - } - } - }; - - /** - * Destroy shell process considering that the process could already be terminated - */ - private void destroyShellProcess() { - try { - // Yes, this really is the way to check if the process is - // still running. - shellProcess.exitValue(); - } catch (IllegalThreadStateException e) { - // Only call destroy() if the process is still running; - // Calling it for a terminated process will not crash, but - // (starting with at least ICS/4.0) spam the log with INFO - // messages ala "Failed to destroy process" and "kill - // failed: ESRCH (No such process)". - shellProcess.destroy(); - } - - Log.d(RootCommands.TAG, "Shell destroyed"); - } - - /** - * Writes queued commands one after another into the opened shell. After an execution a token is - * written to seperate command output on read - * - * @throws java.io.IOException - */ - private void writeCommands() throws IOException { - try { - int commandIndex = 0; - while (true) { - DataOutputStream out; - synchronized (commands) { - while (!close && commandIndex >= commands.size()) { - commands.wait(); - } - out = this.outputStream; - } - if (commandIndex < commands.size()) { - Command next = commands.get(commandIndex); - next.writeCommand(out); - String line = "\necho " + token + " " + commandIndex + " $?\n"; - out.write(line.getBytes()); - out.flush(); - commandIndex++; - } else if (close) { - out.write("\nexit 0\n".getBytes()); - out.flush(); - out.close(); - Log.d(RootCommands.TAG, "Closing shell"); - return; - } - } - } catch (InterruptedException e) { - Log.e(RootCommands.TAG, "interrupted while writing command", e); - } - } - - /** - * Reads output line by line, seperated by token written after every command - * - * @throws java.io.IOException - * @throws InterruptedException - */ - private void readOutput() throws IOException, InterruptedException { - Command command = null; - - // index of current command - int commandIndex = 0; - while (true) { - String lineStdOut = stdOutErr.readLine(); - - // terminate on EOF - if (lineStdOut == null) - break; - - if (command == null) { - - // break on close after last command - if (commandIndex >= commands.size()) { - if (close) - break; - continue; - } - - // get current command - command = commands.get(commandIndex); - } - - int pos = lineStdOut.indexOf(token); - if (pos > 0) { - command.processOutput(lineStdOut.substring(0, pos)); - } - if (pos >= 0) { - lineStdOut = lineStdOut.substring(pos); - String fields[] = lineStdOut.split(" "); - int id = Integer.parseInt(fields[1]); - if (id == commandIndex) { - command.setExitCode(Integer.parseInt(fields[2])); - - // go to next command - commandIndex++; - command = null; - continue; - } - } - command.processOutput(lineStdOut); - } - Log.d(RootCommands.TAG, "Read all output"); - shellProcess.waitFor(); - destroyShellProcess(); - - while (commandIndex < commands.size()) { - if (command == null) { - command = commands.get(commandIndex); - } - command.terminated("Unexpected Termination!"); - commandIndex++; - command = null; - } - } - - /** - * Add command to shell queue - * - * @param command - * @return - * @throws java.io.IOException - */ - public Command add(Command command) throws IOException { - if (close) - throw new IOException("Unable to add commands to a closed shell"); - synchronized (commands) { - commands.add(command); - // set shell on the command object, to know where the command is running on - command.addedToShell(this, (commands.size() - 1)); - commands.notifyAll(); - } - - return command; - } - - /** - * Close shell - * - * @throws java.io.IOException - */ - public void close() throws IOException { - synchronized (commands) { - this.close = true; - commands.notifyAll(); - } - } - - /** - * Returns number of queued commands - * - * @return - */ - public int getCommandsSize() { - return commands.size(); - } - + + +package org.sufficientlysecure.rootcommands; + +import java.io.BufferedReader; +import java.io.Closeable; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.sufficientlysecure.rootcommands.command.Command; +import org.sufficientlysecure.rootcommands.util.Log; +import org.sufficientlysecure.rootcommands.util.RootAccessDeniedException; +import org.sufficientlysecure.rootcommands.util.Utils; + +public class Shell implements Closeable { + private final Process shellProcess; + private final BufferedReader stdOutErr; + private final DataOutputStream outputStream; + private final List commands = new ArrayList(); + private boolean close = false; + + private static final String LD_LIBRARY_PATH = System.getenv("LD_LIBRARY_PATH"); + private static final String token = "F*D^W@#FGF"; + + /** + * Start root shell + * + * @param customEnv + * @param baseDirectory + * @return + * @throws java.io.IOException + */ + public static Shell startRootShell(ArrayList customEnv, String baseDirectory) + throws IOException, RootAccessDeniedException { + Log.d(RootCommands.TAG, "Starting Root Shell!"); + + // On some versions of Android (ICS) LD_LIBRARY_PATH is unset when using su + // We need to pass LD_LIBRARY_PATH over su for some commands to work correctly. + if (customEnv == null) { + customEnv = new ArrayList(); + } + customEnv.add("LD_LIBRARY_PATH=" + LD_LIBRARY_PATH); + + Shell shell = new Shell(Utils.getSuPath(), customEnv, baseDirectory); + + return shell; + } + + /** + * Start root shell without custom environment and base directory + * + * @return + * @throws java.io.IOException + */ + public static Shell startRootShell() throws IOException, RootAccessDeniedException { + return startRootShell(null, null); + } + + /** + * Start default sh shell + * + * @param customEnv + * @param baseDirectory + * @return + * @throws java.io.IOException + */ + public static Shell startShell(ArrayList customEnv, String baseDirectory) + throws IOException { + Log.d(RootCommands.TAG, "Starting Shell!"); + Shell shell = new Shell("sh", customEnv, baseDirectory); + return shell; + } + + /** + * Start default sh shell without custom environment and base directory + * + * @return + * @throws java.io.IOException + */ + public static Shell startShell() throws IOException { + return startShell(null, null); + } + + /** + * Start custom shell defined by shellPath + * + * @param shellPath + * @param customEnv + * @param baseDirectory + * @return + * @throws java.io.IOException + */ + public static Shell startCustomShell(String shellPath, ArrayList customEnv, + String baseDirectory) throws IOException { + Log.d(RootCommands.TAG, "Starting Custom Shell!"); + Shell shell = new Shell(shellPath, customEnv, baseDirectory); + + return shell; + } + + /** + * Start custom shell without custom environment and base directory + * + * @param shellPath + * @return + * @throws java.io.IOException + */ + public static Shell startCustomShell(String shellPath) throws IOException { + return startCustomShell(shellPath, null, null); + } + + private Shell(String shell, ArrayList customEnv, String baseDirectory) + throws IOException, RootAccessDeniedException { + Log.d(RootCommands.TAG, "Starting shell: " + shell); + + // start shell process! + shellProcess = Utils.runWithEnv(shell, customEnv, baseDirectory); + + // StdErr is redirected to StdOut, defined in Command.getCommand() + stdOutErr = new BufferedReader(new InputStreamReader(shellProcess.getInputStream())); + outputStream = new DataOutputStream(shellProcess.getOutputStream()); + + outputStream.write("echo Started\n".getBytes()); + outputStream.flush(); + + while (true) { + String line = stdOutErr.readLine(); + if (line == null) + throw new RootAccessDeniedException( + "stdout line is null! Access was denied or this executeable is not a shell!"); + if ("".equals(line)) + continue; + if ("Started".equals(line)) + break; + + destroyShellProcess(); + throw new IOException("Unable to start shell, unexpected output \"" + line + "\""); + } + + new Thread(inputRunnable, "Shell Input").start(); + new Thread(outputRunnable, "Shell Output").start(); + } + + private Runnable inputRunnable = new Runnable() { + public void run() { + try { + writeCommands(); + } catch (IOException e) { + Log.e(RootCommands.TAG, "IO Exception", e); + } + } + }; + + private Runnable outputRunnable = new Runnable() { + public void run() { + try { + readOutput(); + } catch (IOException e) { + Log.e(RootCommands.TAG, "IOException", e); + } catch (InterruptedException e) { + Log.e(RootCommands.TAG, "InterruptedException", e); + } + } + }; + + /** + * Destroy shell process considering that the process could already be terminated + */ + private void destroyShellProcess() { + try { + // Yes, this really is the way to check if the process is + // still running. + shellProcess.exitValue(); + } catch (IllegalThreadStateException e) { + // Only call destroy() if the process is still running; + // Calling it for a terminated process will not crash, but + // (starting with at least ICS/4.0) spam the log with INFO + // messages ala "Failed to destroy process" and "kill + // failed: ESRCH (No such process)". + shellProcess.destroy(); + } + + Log.d(RootCommands.TAG, "Shell destroyed"); + } + + /** + * Writes queued commands one after another into the opened shell. After an execution a token is + * written to seperate command output on read + * + * @throws java.io.IOException + */ + private void writeCommands() throws IOException { + try { + int commandIndex = 0; + while (true) { + DataOutputStream out; + synchronized (commands) { + while (!close && commandIndex >= commands.size()) { + commands.wait(); + } + out = this.outputStream; + } + if (commandIndex < commands.size()) { + Command next = commands.get(commandIndex); + next.writeCommand(out); + String line = "\necho " + token + " " + commandIndex + " $?\n"; + out.write(line.getBytes()); + out.flush(); + commandIndex++; + } else if (close) { + out.write("\nexit 0\n".getBytes()); + out.flush(); + out.close(); + Log.d(RootCommands.TAG, "Closing shell"); + return; + } + } + } catch (InterruptedException e) { + Log.e(RootCommands.TAG, "interrupted while writing command", e); + } + } + + /** + * Reads output line by line, seperated by token written after every command + * + * @throws java.io.IOException + * @throws InterruptedException + */ + private void readOutput() throws IOException, InterruptedException { + Command command = null; + + // index of current command + int commandIndex = 0; + while (true) { + String lineStdOut = stdOutErr.readLine(); + + // terminate on EOF + if (lineStdOut == null) + break; + + if (command == null) { + + // break on close after last command + if (commandIndex >= commands.size()) { + if (close) + break; + continue; + } + + // get current command + command = commands.get(commandIndex); + } + + int pos = lineStdOut.indexOf(token); + if (pos > 0) { + command.processOutput(lineStdOut.substring(0, pos)); + } + if (pos >= 0) { + lineStdOut = lineStdOut.substring(pos); + String fields[] = lineStdOut.split(" "); + int id = Integer.parseInt(fields[1]); + if (id == commandIndex) { + command.setExitCode(Integer.parseInt(fields[2])); + + // go to next command + commandIndex++; + command = null; + continue; + } + } + command.processOutput(lineStdOut); + } + Log.d(RootCommands.TAG, "Read all output"); + shellProcess.waitFor(); + destroyShellProcess(); + + while (commandIndex < commands.size()) { + if (command == null) { + command = commands.get(commandIndex); + } + command.terminated("Unexpected Termination!"); + commandIndex++; + command = null; + } + } + + /** + * Add command to shell queue + * + * @param command + * @return + * @throws java.io.IOException + */ + public Command add(Command command) throws IOException { + if (close) + throw new IOException("Unable to add commands to a closed shell"); + synchronized (commands) { + commands.add(command); + // set shell on the command object, to know where the command is running on + command.addedToShell(this, (commands.size() - 1)); + commands.notifyAll(); + } + + return command; + } + + /** + * Close shell + * + * @throws java.io.IOException + */ + public void close() throws IOException { + synchronized (commands) { + this.close = true; + commands.notifyAll(); + } + } + + /** + * Returns number of queued commands + * + * @return + */ + public int getCommandsSize() { + return commands.size(); + } + } \ No newline at end of file diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/SystemCommands.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/SystemCommands.java index fa4a551..84b4f80 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/SystemCommands.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/SystemCommands.java @@ -1,108 +1,108 @@ - - -package org.sufficientlysecure.rootcommands; - -import android.annotation.TargetApi; -import android.content.ContentResolver; -import android.content.Context; -import android.location.LocationManager; -import android.os.PowerManager; -import android.provider.Settings; - -/** - * This methods work when the apk is installed as a system app (under /system/app) - */ -public class SystemCommands { - Context context; - - public SystemCommands(Context context) { - super(); - this.context = context; - } - - /** - * Get GPS status - * - * @return - */ - public boolean getGPS() { - return ((LocationManager) context.getSystemService(Context.LOCATION_SERVICE)) - .isProviderEnabled(LocationManager.GPS_PROVIDER); - } - - /** - * Enable/Disable GPS - * - * @param value - */ - @TargetApi(8) - public void setGPS(boolean value) { - ContentResolver localContentResolver = context.getContentResolver(); - Settings.Secure.setLocationProviderEnabled(localContentResolver, - LocationManager.GPS_PROVIDER, value); - } - - /** - * TODO: Not ready yet - */ - @TargetApi(8) - public void reboot() { - PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - pm.reboot("recovery"); - pm.reboot(null); - - // not working: - // reboot(null); - } - - /** - * Reboot the device immediately, passing 'reason' (may be null) to the underlying __reboot - * system call. Should not return. - * - * Taken from com.android.server.PowerManagerService.reboot - */ - // public void reboot(String reason) { - // - // // final String finalReason = reason; - // Runnable runnable = new Runnable() { - // public void run() { - // synchronized (this) { - // // ShutdownThread.reboot(mContext, finalReason, false); - // try { - // Class clazz = Class.forName("com.android.internal.app.ShutdownThread"); - // - // // if (mReboot) { - // Method method = clazz.getMethod("reboot", Context.class, String.class, - // Boolean.TYPE); - // method.invoke(null, context, null, false); - // - // // if (mReboot) { - // // Method method = clazz.getMethod("reboot", Context.class, String.class, - // // Boolean.TYPE); - // // method.invoke(null, mContext, mReason, mConfirm); - // // } else { - // // Method method = clazz.getMethod("shutdown", Context.class, Boolean.TYPE); - // // method.invoke(null, mContext, mConfirm); - // // } - // } catch (Exception e) { - // e.printStackTrace(); - // } - // } - // - // } - // }; - // // ShutdownThread must run on a looper capable of displaying the UI. - // mHandler.post(runnable); - // - // // PowerManager.reboot() is documented not to return so just wait for the inevitable. - // // synchronized (runnable) { - // // while (true) { - // // try { - // // runnable.wait(); - // // } catch (InterruptedException e) { - // // } - // // } - // // } - // } - -} + + +package org.sufficientlysecure.rootcommands; + +import android.annotation.TargetApi; +import android.content.ContentResolver; +import android.content.Context; +import android.location.LocationManager; +import android.os.PowerManager; +import android.provider.Settings; + +/** + * This methods work when the apk is installed as a system app (under /system/app) + */ +public class SystemCommands { + Context context; + + public SystemCommands(Context context) { + super(); + this.context = context; + } + + /** + * Get GPS status + * + * @return + */ + public boolean getGPS() { + return ((LocationManager) context.getSystemService(Context.LOCATION_SERVICE)) + .isProviderEnabled(LocationManager.GPS_PROVIDER); + } + + /** + * Enable/Disable GPS + * + * @param value + */ + @TargetApi(8) + public void setGPS(boolean value) { + ContentResolver localContentResolver = context.getContentResolver(); + Settings.Secure.setLocationProviderEnabled(localContentResolver, + LocationManager.GPS_PROVIDER, value); + } + + /** + * TODO: Not ready yet + */ + @TargetApi(8) + public void reboot() { + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + pm.reboot("recovery"); + pm.reboot(null); + + // not working: + // reboot(null); + } + + /** + * Reboot the device immediately, passing 'reason' (may be null) to the underlying __reboot + * system call. Should not return. + * + * Taken from com.android.server.PowerManagerService.reboot + */ + // public void reboot(String reason) { + // + // // final String finalReason = reason; + // Runnable runnable = new Runnable() { + // public void run() { + // synchronized (this) { + // // ShutdownThread.reboot(mContext, finalReason, false); + // try { + // Class clazz = Class.forName("com.android.internal.app.ShutdownThread"); + // + // // if (mReboot) { + // Method method = clazz.getMethod("reboot", Context.class, String.class, + // Boolean.TYPE); + // method.invoke(null, context, null, false); + // + // // if (mReboot) { + // // Method method = clazz.getMethod("reboot", Context.class, String.class, + // // Boolean.TYPE); + // // method.invoke(null, mContext, mReason, mConfirm); + // // } else { + // // Method method = clazz.getMethod("shutdown", Context.class, Boolean.TYPE); + // // method.invoke(null, mContext, mConfirm); + // // } + // } catch (Exception e) { + // e.printStackTrace(); + // } + // } + // + // } + // }; + // // ShutdownThread must run on a looper capable of displaying the UI. + // mHandler.post(runnable); + // + // // PowerManager.reboot() is documented not to return so just wait for the inevitable. + // // synchronized (runnable) { + // // while (true) { + // // try { + // // runnable.wait(); + // // } catch (InterruptedException e) { + // // } + // // } + // // } + // } + +} diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Toolbox.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Toolbox.java index 177b016..af869d9 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Toolbox.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Toolbox.java @@ -1,809 +1,809 @@ - - -package org.sufficientlysecure.rootcommands; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.concurrent.TimeoutException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.sufficientlysecure.rootcommands.command.ExecutableCommand; -import org.sufficientlysecure.rootcommands.command.Command; -import org.sufficientlysecure.rootcommands.command.SimpleCommand; -import org.sufficientlysecure.rootcommands.util.BrokenBusyboxException; -import org.sufficientlysecure.rootcommands.util.Log; - -import android.os.StatFs; -import android.os.SystemClock; - -/** - * All methods in this class are working with Androids toolbox. Toolbox is similar to busybox, but - * normally shipped on every Android OS. You can find toolbox commands on - * https://github.com/CyanogenMod/android_system_core/tree/ics/toolbox - * - * This means that these commands are designed to work on every Android OS, with a _working_ toolbox - * binary on it. They don't require busybox! - * - */ -public class Toolbox { - private Shell shell; - - /** - * All methods in this class are working with Androids toolbox. Toolbox is similar to busybox, - * but normally shipped on every Android OS. - * - * @param shell - * where to execute commands on - */ - public Toolbox(Shell shell) { - super(); - this.shell = shell; - } - - /** - * Checks if user accepted root access - * - * (commands: id) - * - * @return true if user has given root access - * @throws java.io.IOException - * @throws java.util.concurrent.TimeoutException - * @throws BrokenBusyboxException - */ - public boolean isRootAccessGiven() throws BrokenBusyboxException, TimeoutException, IOException { - SimpleCommand idCommand = new SimpleCommand("id"); - shell.add(idCommand).waitForFinish(); - - if (idCommand.getOutput().contains("uid=0")) { - return true; - } else { - return false; - } - } - - /** - * This command class gets all pids to a given process name - */ - private class PsCommand extends Command { - private String processName; - private ArrayList pids; - private String psRegex; - private Pattern psPattern; - - public PsCommand(String processName) { - super("ps"); - this.processName = processName; - pids = new ArrayList(); - - /** - * regex to get pid out of ps line, example: - * - *

-             *  root    24736    1   12140  584   ffffffff 40010d14 S /data/data/org.adaway/files/blank_webserver
-             * ^\\S \\s ([0-9]+)                          .*                                      processName    $
-             * 
- */ - psRegex = "^\\S+\\s+([0-9]+).*" + Pattern.quote(processName) + "$"; - psPattern = Pattern.compile(psRegex); - } - - public ArrayList getPids() { - return pids; - } - - public String getPidsString() { - StringBuilder sb = new StringBuilder(); - for (String s : pids) { - sb.append(s); - sb.append(" "); - } - - return sb.toString(); - } - - @Override - public void output(int id, String line) { - // general check if line contains processName - if (line.contains(processName)) { - Matcher psMatcher = psPattern.matcher(line); - - // try to match line exactly - try { - if (psMatcher.find()) { - String pid = psMatcher.group(1); - // add to pids list - pids.add(pid); - Log.d(RootCommands.TAG, "Found pid: " + pid); - } else { - Log.d(RootCommands.TAG, "Matching in ps command failed!"); - } - } catch (Exception e) { - Log.e(RootCommands.TAG, "Error with regex!", e); - } - } - } - - @Override - public void afterExecution(int id, int exitCode) { - } - - } - - /** - * This method can be used to kill a running process - * - * (commands: ps, kill) - * - * @param processName - * name of process to kill - * @return true if process was found and killed successfully - * @throws java.io.IOException - * @throws java.util.concurrent.TimeoutException - * @throws BrokenBusyboxException - */ - public boolean killAll(String processName) throws BrokenBusyboxException, TimeoutException, - IOException { - Log.d(RootCommands.TAG, "Killing process " + processName); - - PsCommand psCommand = new PsCommand(processName); - shell.add(psCommand).waitForFinish(); - - // kill processes - if (!psCommand.getPids().isEmpty()) { - // example: kill -9 1234 1222 5343 - SimpleCommand killCommand = new SimpleCommand("kill -9 " - + psCommand.getPidsString()); - shell.add(killCommand).waitForFinish(); - - if (killCommand.getExitCode() == 0) { - return true; - } else { - return false; - } - } else { - Log.d(RootCommands.TAG, "No pid found! Nothing was killed!"); - return false; - } - } - - /** - * Kill a running executable - * - * See README for more information how to use your own executables! - * - * @param executableName - * @return - * @throws BrokenBusyboxException - * @throws java.util.concurrent.TimeoutException - * @throws java.io.IOException - */ - public boolean killAllExecutable(String executableName) throws BrokenBusyboxException, - TimeoutException, IOException { - return killAll(ExecutableCommand.EXECUTABLE_PREFIX + executableName + ExecutableCommand.EXECUTABLE_SUFFIX); - } - - /** - * This method can be used to to check if a process is running - * - * @param processName - * name of process to check - * @return true if process was found - * @throws java.io.IOException - * @throws BrokenBusyboxException - * @throws java.util.concurrent.TimeoutException - * (Could not determine if the process is running) - */ - public boolean isProcessRunning(String processName) throws BrokenBusyboxException, - TimeoutException, IOException { - PsCommand psCommand = new PsCommand(processName); - shell.add(psCommand).waitForFinish(); - - // if pids are available process is running! - if (!psCommand.getPids().isEmpty()) { - return true; - } else { - return false; - } - } - - /** - * Checks if binary is running - * - * @param binaryName - * @return - * @throws BrokenBusyboxException - * @throws java.util.concurrent.TimeoutException - * @throws java.io.IOException - */ - public boolean isBinaryRunning(String binaryName) throws BrokenBusyboxException, - TimeoutException, IOException { - return isProcessRunning(ExecutableCommand.EXECUTABLE_PREFIX + binaryName - + ExecutableCommand.EXECUTABLE_SUFFIX); - } - - /** - * Ls command to get permissions or symlinks - */ - private class LsCommand extends Command { - private String fileName; - private String permissionRegex; - private Pattern permissionPattern; - private String symlinkRegex; - private Pattern symlinkPattern; - - private String symlink; - private String permissions; - - public String getSymlink() { - return symlink; - } - - public String getPermissions() { - return permissions; - } - - public LsCommand(String file) { - super("ls -l " + file); - - // get only filename: - this.fileName = (new File(file)).getName(); - Log.d(RootCommands.TAG, "fileName: " + fileName); - - /** - * regex to get pid out of ps line, example: - * - *
-             * with busybox:
-             *     lrwxrwxrwx     1 root root            15 Aug 13 12:14 dev/stdin -> /proc/self/fd/0
-             *     
-             * with toolbox:
-             *     lrwxrwxrwx root root            15 Aug 13 12:14 stdin -> /proc/self/fd/0
-             * 
-             * Regex:
-             * ^.*?(\\S{10})                     .*                                                  $
-             * 
- */ - permissionRegex = "^.*?(\\S{10}).*$"; - permissionPattern = Pattern.compile(permissionRegex); - - /** - * regex to get symlink - * - *
-             *     ->           /proc/self/fd/0
-             * ^.*?\\-\\> \\s+  (.*)           $
-             * 
- */ - symlinkRegex = "^.*?\\-\\>\\s+(.*)$"; - symlinkPattern = Pattern.compile(symlinkRegex); - } - - /** - * Converts permission string from ls command to numerical value. Example: -rwxrwxrwx gets - * to 777 - * - * @param permissions - * @return - */ - private String convertPermissions(String permissions) { - int owner = getGroupPermission(permissions.substring(1, 4)); - int group = getGroupPermission(permissions.substring(4, 7)); - int world = getGroupPermission(permissions.substring(7, 10)); - - return "" + owner + group + world; - } - - /** - * Calculates permission for one group - * - * @param permission - * @return value of permission string - */ - private int getGroupPermission(String permission) { - int value = 0; - - if (permission.charAt(0) == 'r') { - value += 4; - } - if (permission.charAt(1) == 'w') { - value += 2; - } - if (permission.charAt(2) == 'x') { - value += 1; - } - - return value; - } - - @Override - public void output(int id, String line) { - // general check if line contains file - if (line.contains(fileName)) { - - // try to match line exactly - try { - Matcher permissionMatcher = permissionPattern.matcher(line); - if (permissionMatcher.find()) { - permissions = convertPermissions(permissionMatcher.group(1)); - - Log.d(RootCommands.TAG, "Found permissions: " + permissions); - } else { - Log.d(RootCommands.TAG, "Permissions were not found in ls command!"); - } - - // try to parse for symlink - Matcher symlinkMatcher = symlinkPattern.matcher(line); - if (symlinkMatcher.find()) { - /* - * TODO: If symlink points to a file in the same directory the path is not - * absolute!!! - */ - symlink = symlinkMatcher.group(1); - Log.d(RootCommands.TAG, "Symlink found: " + symlink); - } else { - Log.d(RootCommands.TAG, "No symlink found!"); - } - } catch (Exception e) { - Log.e(RootCommands.TAG, "Error with regex!", e); - } - } - } - - @Override - public void afterExecution(int id, int exitCode) { - } - - } - - /** - * @param file - * String that represent the file, including the full path to the file and its name. - * @param followSymlinks - * @return File permissions as String, for example: 777, returns null on error - * @throws java.io.IOException - * @throws java.util.concurrent.TimeoutException - * @throws BrokenBusyboxException - * - */ - public String getFilePermissions(String file) throws BrokenBusyboxException, TimeoutException, - IOException { - Log.d(RootCommands.TAG, "Checking permissions for " + file); - - String permissions = null; - - if (fileExists(file)) { - Log.d(RootCommands.TAG, file + " was found."); - - LsCommand lsCommand = new LsCommand(file); - shell.add(lsCommand).waitForFinish(); - - permissions = lsCommand.getPermissions(); - } - - return permissions; - } - - /** - * Sets permission of file - * - * @param file - * absolute path to file - * @param permissions - * String like 777 - * @return true if command worked - * @throws BrokenBusyboxException - * @throws java.util.concurrent.TimeoutException - * @throws java.io.IOException - */ - public boolean setFilePermissions(String file, String permissions) - throws BrokenBusyboxException, TimeoutException, IOException { - Log.d(RootCommands.TAG, "Set permissions of " + file + " to " + permissions); - - SimpleCommand chmodCommand = new SimpleCommand("chmod " + permissions + " " + file); - shell.add(chmodCommand).waitForFinish(); - - if (chmodCommand.getExitCode() == 0) { - return true; - } else { - return false; - } - } - - /** - * This will return a String that represent the symlink for a specified file. - * - * @param file - * The path to the file to get the Symlink for. (must have absolute path) - * - * @return A String that represent the symlink for a specified file or null if no symlink - * exists. - * @throws java.io.IOException - * @throws java.util.concurrent.TimeoutException - * @throws BrokenBusyboxException - */ - public String getSymlink(String file) throws BrokenBusyboxException, TimeoutException, - IOException { - Log.d(RootCommands.TAG, "Find symlink for " + file); - - String symlink = null; - - LsCommand lsCommand = new LsCommand(file); - shell.add(lsCommand).waitForFinish(); - - symlink = lsCommand.getSymlink(); - - return symlink; - } - - /** - * Copys a file to a destination. Because cp is not available on all android devices, we use dd - * or cat. - * - * @param source - * example: /data/data/org.adaway/files/hosts - * @param destination - * example: /system/etc/hosts - * @param remountAsRw - * remounts the destination as read/write before writing to it - * @param preserveFileAttributes - * tries to copy file attributes from source to destination, if only cat is available - * only permissions are preserved - * @return true if it was successfully copied - * @throws BrokenBusyboxException - * @throws java.io.IOException - * @throws java.util.concurrent.TimeoutException - */ - public boolean copyFile(String source, String destination, boolean remountAsRw, - boolean preservePermissions) throws BrokenBusyboxException, IOException, - TimeoutException { - - /* - * dd can only copy files, but we can not check if the source is a file without invoking - * shell commands, because from Java we probably have no read access, thus we only check if - * they are ending with trailing slashes - */ - if (source.endsWith("/") || destination.endsWith("/")) { - throw new FileNotFoundException("dd can only copy files!"); - } - - // remount destination as read/write before copying to it - if (remountAsRw) { - if (!remount(destination, "RW")) { - Log.d(RootCommands.TAG, - "Remounting failed! There is probably no need to remount this partition!"); - } - } - - // get permissions of source before overwriting - String permissions = null; - if (preservePermissions) { - permissions = getFilePermissions(source); - } - - boolean commandSuccess = false; - - SimpleCommand ddCommand = new SimpleCommand("dd if=" + source + " of=" - + destination); - shell.add(ddCommand).waitForFinish(); - - if (ddCommand.getExitCode() == 0) { - commandSuccess = true; - } else { - // try cat if dd fails - SimpleCommand catCommand = new SimpleCommand("cat " + source + " > " - + destination); - shell.add(catCommand).waitForFinish(); - - if (catCommand.getExitCode() == 0) { - commandSuccess = true; - } - } - - // set back permissions from source to destination - if (preservePermissions) { - setFilePermissions(destination, permissions); - } - - // remount destination back to read only - if (remountAsRw) { - if (!remount(destination, "RO")) { - Log.d(RootCommands.TAG, - "Remounting failed! There is probably no need to remount this partition!"); - } - } - - return commandSuccess; - } - - public static final int REBOOT_HOTREBOOT = 1; - public static final int REBOOT_REBOOT = 2; - public static final int REBOOT_SHUTDOWN = 3; - public static final int REBOOT_RECOVERY = 4; - - /** - * Shutdown or reboot device. Possible actions are REBOOT_HOTREBOOT, REBOOT_REBOOT, - * REBOOT_SHUTDOWN, REBOOT_RECOVERY - * - * @param action - * @throws java.io.IOException - * @throws java.util.concurrent.TimeoutException - * @throws BrokenBusyboxException - */ - public void reboot(int action) throws BrokenBusyboxException, TimeoutException, IOException { - if (action == REBOOT_HOTREBOOT) { - killAll("system_server"); - // or: killAll("zygote"); - } else { - String command; - switch (action) { - case REBOOT_REBOOT: - command = "reboot"; - break; - case REBOOT_SHUTDOWN: - command = "reboot -p"; - break; - case REBOOT_RECOVERY: - command = "reboot recovery"; - break; - default: - command = "reboot"; - break; - } - - SimpleCommand rebootCommand = new SimpleCommand(command); - shell.add(rebootCommand).waitForFinish(); - - if (rebootCommand.getExitCode() == -1) { - Log.e(RootCommands.TAG, "Reboot failed!"); - } - } - } - - /** - * This command checks if a file exists - */ - private class FileExistsCommand extends Command { - private String file; - private boolean fileExists = false; - - public FileExistsCommand(String file) { - super("ls " + file); - this.file = file; - } - - public boolean isFileExists() { - return fileExists; - } - - @Override - public void output(int id, String line) { - if (line.trim().equals(file)) { - fileExists = true; - } - } - - @Override - public void afterExecution(int id, int exitCode) { - } - - } - - /** - * Use this to check whether or not a file exists on the filesystem. - * - * @param file - * String that represent the file, including the full path to the file and its name. - * - * @return a boolean that will indicate whether or not the file exists. - * @throws java.io.IOException - * @throws java.util.concurrent.TimeoutException - * @throws BrokenBusyboxException - * - */ - public boolean fileExists(String file) throws BrokenBusyboxException, TimeoutException, - IOException { - FileExistsCommand fileExistsCommand = new FileExistsCommand(file); - shell.add(fileExistsCommand).waitForFinish(); - - if (fileExistsCommand.isFileExists()) { - return true; - } else { - return false; - } - } - - public abstract class WithPermissions { - abstract void whileHavingPermissions(); - } - - /** - * Execute user defined Java code while having temporary permissions on a file - * - * @param file - * @param withPermissions - * @throws BrokenBusyboxException - * @throws java.util.concurrent.TimeoutException - * @throws java.io.IOException - */ - public void withPermission(String file, String permission, WithPermissions withPermissions) - throws BrokenBusyboxException, TimeoutException, IOException { - String oldPermissions = getFilePermissions(file); - - // set permissions (If set to 666, then Dalvik VM can also write to that file!) - setFilePermissions(file, permission); - - // execute user defined code - withPermissions.whileHavingPermissions(); - - // set back to old permissions - setFilePermissions(file, oldPermissions); - } - - /** - * Execute user defined Java code while having temporary write permissions on a file using chmod - * 666 - * - * @param file - * @param withWritePermissions - * @throws BrokenBusyboxException - * @throws java.util.concurrent.TimeoutException - * @throws java.io.IOException - */ - public void withWritePermissions(String file, WithPermissions withWritePermissions) - throws BrokenBusyboxException, TimeoutException, IOException { - withPermission(file, "666", withWritePermissions); - } - - /** - * Sets system clock using /dev/alarm - * - * @param millis - * @throws BrokenBusyboxException - * @throws java.util.concurrent.TimeoutException - * @throws java.io.IOException - */ - public void setSystemClock(final long millis) throws BrokenBusyboxException, TimeoutException, - IOException { - withWritePermissions("/dev/alarm", new WithPermissions() { - - @Override - void whileHavingPermissions() { - SystemClock.setCurrentTimeMillis(millis); - } - }); - } - - /** - * Adjust system clock by offset using /dev/alarm - * - * @param offset - * @throws BrokenBusyboxException - * @throws java.util.concurrent.TimeoutException - * @throws java.io.IOException - */ - public void adjustSystemClock(final long offset) throws BrokenBusyboxException, - TimeoutException, IOException { - withWritePermissions("/dev/alarm", new WithPermissions() { - - @Override - void whileHavingPermissions() { - SystemClock.setCurrentTimeMillis(System.currentTimeMillis() + offset); - } - }); - } - - /** - * This will take a path, which can contain the file name as well, and attempt to remount the - * underlying partition. - * - * For example, passing in the following string: - * "/system/bin/some/directory/that/really/would/never/exist" will result in /system ultimately - * being remounted. However, keep in mind that the longer the path you supply, the more work - * this has to do, and the slower it will run. - * - * @param file - * file path - * @param mountType - * mount type: pass in RO (Read only) or RW (Read Write) - * @return a boolean which indicates whether or not the partition has been - * remounted as specified. - */ - public boolean remount(String file, String mountType) { - // Recieved a request, get an instance of Remounter - Remounter remounter = new Remounter(shell); - // send the request - return (remounter.remount(file, mountType)); - } - - /** - * This will tell you how the specified mount is mounted. rw, ro, etc... - * - * @param The - * mount you want to check - * - * @return String What the mount is mounted as. - * @throws Exception - * if we cannot determine how the mount is mounted. - */ - public String getMountedAs(String path) throws Exception { - ArrayList mounts = Remounter.getMounts(); - if (mounts != null) { - for (Mount mount : mounts) { - if (path.contains(mount.getMountPoint().getAbsolutePath())) { - Log.d(RootCommands.TAG, (String) mount.getFlags().toArray()[0]); - return (String) mount.getFlags().toArray()[0]; - } - } - - throw new Exception(); - } else { - throw new Exception(); - } - } - - /** - * Check if there is enough space on partition where target is located - * - * @param size - * size of file to put on partition - * @param target - * path where to put the file - * - * @return true if it will fit on partition of target, false if it will not fit. - */ - public boolean hasEnoughSpaceOnPartition(String target, long size) { - try { - // new File(target).getFreeSpace() (API 9) is not working on data partition - - // get directory without file - String directory = new File(target).getParent().toString(); - - StatFs stat = new StatFs(directory); - long blockSize = stat.getBlockSize(); - long availableBlocks = stat.getAvailableBlocks(); - long availableSpace = availableBlocks * blockSize; - - Log.i(RootCommands.TAG, "Checking for enough space: Target: " + target - + ", directory: " + directory + " size: " + size + ", availableSpace: " - + availableSpace); - - if (size < availableSpace) { - return true; - } else { - Log.e(RootCommands.TAG, "Not enough space on partition!"); - return false; - } - } catch (Exception e) { - // if new StatFs(directory) fails catch IllegalArgumentException and just return true as - // workaround - Log.e(RootCommands.TAG, "Problem while getting available space on partition!", e); - return true; - } - } - - /** - * TODO: Not tested! - * - * @param toggle - * @throws java.io.IOException - * @throws java.util.concurrent.TimeoutException - * @throws BrokenBusyboxException - */ - public void toggleAdbDaemon(boolean toggle) throws BrokenBusyboxException, TimeoutException, - IOException { - SimpleCommand disableAdb = new SimpleCommand("setprop persist.service.adb.enable 0", - "stop adbd"); - SimpleCommand enableAdb = new SimpleCommand("setprop persist.service.adb.enable 1", - "stop adbd", "sleep 1", "start adbd"); - - if (toggle) { - shell.add(enableAdb).waitForFinish(); - } else { - shell.add(disableAdb).waitForFinish(); - } - } - -} + + +package org.sufficientlysecure.rootcommands; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.concurrent.TimeoutException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.sufficientlysecure.rootcommands.command.ExecutableCommand; +import org.sufficientlysecure.rootcommands.command.Command; +import org.sufficientlysecure.rootcommands.command.SimpleCommand; +import org.sufficientlysecure.rootcommands.util.BrokenBusyboxException; +import org.sufficientlysecure.rootcommands.util.Log; + +import android.os.StatFs; +import android.os.SystemClock; + +/** + * All methods in this class are working with Androids toolbox. Toolbox is similar to busybox, but + * normally shipped on every Android OS. You can find toolbox commands on + * https://github.com/CyanogenMod/android_system_core/tree/ics/toolbox + * + * This means that these commands are designed to work on every Android OS, with a _working_ toolbox + * binary on it. They don't require busybox! + * + */ +public class Toolbox { + private Shell shell; + + /** + * All methods in this class are working with Androids toolbox. Toolbox is similar to busybox, + * but normally shipped on every Android OS. + * + * @param shell + * where to execute commands on + */ + public Toolbox(Shell shell) { + super(); + this.shell = shell; + } + + /** + * Checks if user accepted root access + * + * (commands: id) + * + * @return true if user has given root access + * @throws java.io.IOException + * @throws java.util.concurrent.TimeoutException + * @throws BrokenBusyboxException + */ + public boolean isRootAccessGiven() throws BrokenBusyboxException, TimeoutException, IOException { + SimpleCommand idCommand = new SimpleCommand("id"); + shell.add(idCommand).waitForFinish(); + + if (idCommand.getOutput().contains("uid=0")) { + return true; + } else { + return false; + } + } + + /** + * This command class gets all pids to a given process name + */ + private class PsCommand extends Command { + private String processName; + private ArrayList pids; + private String psRegex; + private Pattern psPattern; + + public PsCommand(String processName) { + super("ps"); + this.processName = processName; + pids = new ArrayList(); + + /** + * regex to get pid out of ps line, example: + * + *
+             *  root    24736    1   12140  584   ffffffff 40010d14 S /data/data/org.adaway/files/blank_webserver
+             * ^\\S \\s ([0-9]+)                          .*                                      processName    $
+             * 
+ */ + psRegex = "^\\S+\\s+([0-9]+).*" + Pattern.quote(processName) + "$"; + psPattern = Pattern.compile(psRegex); + } + + public ArrayList getPids() { + return pids; + } + + public String getPidsString() { + StringBuilder sb = new StringBuilder(); + for (String s : pids) { + sb.append(s); + sb.append(" "); + } + + return sb.toString(); + } + + @Override + public void output(int id, String line) { + // general check if line contains processName + if (line.contains(processName)) { + Matcher psMatcher = psPattern.matcher(line); + + // try to match line exactly + try { + if (psMatcher.find()) { + String pid = psMatcher.group(1); + // add to pids list + pids.add(pid); + Log.d(RootCommands.TAG, "Found pid: " + pid); + } else { + Log.d(RootCommands.TAG, "Matching in ps command failed!"); + } + } catch (Exception e) { + Log.e(RootCommands.TAG, "Error with regex!", e); + } + } + } + + @Override + public void afterExecution(int id, int exitCode) { + } + + } + + /** + * This method can be used to kill a running process + * + * (commands: ps, kill) + * + * @param processName + * name of process to kill + * @return true if process was found and killed successfully + * @throws java.io.IOException + * @throws java.util.concurrent.TimeoutException + * @throws BrokenBusyboxException + */ + public boolean killAll(String processName) throws BrokenBusyboxException, TimeoutException, + IOException { + Log.d(RootCommands.TAG, "Killing process " + processName); + + PsCommand psCommand = new PsCommand(processName); + shell.add(psCommand).waitForFinish(); + + // kill processes + if (!psCommand.getPids().isEmpty()) { + // example: kill -9 1234 1222 5343 + SimpleCommand killCommand = new SimpleCommand("kill -9 " + + psCommand.getPidsString()); + shell.add(killCommand).waitForFinish(); + + if (killCommand.getExitCode() == 0) { + return true; + } else { + return false; + } + } else { + Log.d(RootCommands.TAG, "No pid found! Nothing was killed!"); + return false; + } + } + + /** + * Kill a running executable + * + * See README for more information how to use your own executables! + * + * @param executableName + * @return + * @throws BrokenBusyboxException + * @throws java.util.concurrent.TimeoutException + * @throws java.io.IOException + */ + public boolean killAllExecutable(String executableName) throws BrokenBusyboxException, + TimeoutException, IOException { + return killAll(ExecutableCommand.EXECUTABLE_PREFIX + executableName + ExecutableCommand.EXECUTABLE_SUFFIX); + } + + /** + * This method can be used to to check if a process is running + * + * @param processName + * name of process to check + * @return true if process was found + * @throws java.io.IOException + * @throws BrokenBusyboxException + * @throws java.util.concurrent.TimeoutException + * (Could not determine if the process is running) + */ + public boolean isProcessRunning(String processName) throws BrokenBusyboxException, + TimeoutException, IOException { + PsCommand psCommand = new PsCommand(processName); + shell.add(psCommand).waitForFinish(); + + // if pids are available process is running! + if (!psCommand.getPids().isEmpty()) { + return true; + } else { + return false; + } + } + + /** + * Checks if binary is running + * + * @param binaryName + * @return + * @throws BrokenBusyboxException + * @throws java.util.concurrent.TimeoutException + * @throws java.io.IOException + */ + public boolean isBinaryRunning(String binaryName) throws BrokenBusyboxException, + TimeoutException, IOException { + return isProcessRunning(ExecutableCommand.EXECUTABLE_PREFIX + binaryName + + ExecutableCommand.EXECUTABLE_SUFFIX); + } + + /** + * Ls command to get permissions or symlinks + */ + private class LsCommand extends Command { + private String fileName; + private String permissionRegex; + private Pattern permissionPattern; + private String symlinkRegex; + private Pattern symlinkPattern; + + private String symlink; + private String permissions; + + public String getSymlink() { + return symlink; + } + + public String getPermissions() { + return permissions; + } + + public LsCommand(String file) { + super("ls -l " + file); + + // get only filename: + this.fileName = (new File(file)).getName(); + Log.d(RootCommands.TAG, "fileName: " + fileName); + + /** + * regex to get pid out of ps line, example: + * + *
+             * with busybox:
+             *     lrwxrwxrwx     1 root root            15 Aug 13 12:14 dev/stdin -> /proc/self/fd/0
+             *     
+             * with toolbox:
+             *     lrwxrwxrwx root root            15 Aug 13 12:14 stdin -> /proc/self/fd/0
+             * 
+             * Regex:
+             * ^.*?(\\S{10})                     .*                                                  $
+             * 
+ */ + permissionRegex = "^.*?(\\S{10}).*$"; + permissionPattern = Pattern.compile(permissionRegex); + + /** + * regex to get symlink + * + *
+             *     ->           /proc/self/fd/0
+             * ^.*?\\-\\> \\s+  (.*)           $
+             * 
+ */ + symlinkRegex = "^.*?\\-\\>\\s+(.*)$"; + symlinkPattern = Pattern.compile(symlinkRegex); + } + + /** + * Converts permission string from ls command to numerical value. Example: -rwxrwxrwx gets + * to 777 + * + * @param permissions + * @return + */ + private String convertPermissions(String permissions) { + int owner = getGroupPermission(permissions.substring(1, 4)); + int group = getGroupPermission(permissions.substring(4, 7)); + int world = getGroupPermission(permissions.substring(7, 10)); + + return "" + owner + group + world; + } + + /** + * Calculates permission for one group + * + * @param permission + * @return value of permission string + */ + private int getGroupPermission(String permission) { + int value = 0; + + if (permission.charAt(0) == 'r') { + value += 4; + } + if (permission.charAt(1) == 'w') { + value += 2; + } + if (permission.charAt(2) == 'x') { + value += 1; + } + + return value; + } + + @Override + public void output(int id, String line) { + // general check if line contains file + if (line.contains(fileName)) { + + // try to match line exactly + try { + Matcher permissionMatcher = permissionPattern.matcher(line); + if (permissionMatcher.find()) { + permissions = convertPermissions(permissionMatcher.group(1)); + + Log.d(RootCommands.TAG, "Found permissions: " + permissions); + } else { + Log.d(RootCommands.TAG, "Permissions were not found in ls command!"); + } + + // try to parse for symlink + Matcher symlinkMatcher = symlinkPattern.matcher(line); + if (symlinkMatcher.find()) { + /* + * TODO: If symlink points to a file in the same directory the path is not + * absolute!!! + */ + symlink = symlinkMatcher.group(1); + Log.d(RootCommands.TAG, "Symlink found: " + symlink); + } else { + Log.d(RootCommands.TAG, "No symlink found!"); + } + } catch (Exception e) { + Log.e(RootCommands.TAG, "Error with regex!", e); + } + } + } + + @Override + public void afterExecution(int id, int exitCode) { + } + + } + + /** + * @param file + * String that represent the file, including the full path to the file and its name. + * @param followSymlinks + * @return File permissions as String, for example: 777, returns null on error + * @throws java.io.IOException + * @throws java.util.concurrent.TimeoutException + * @throws BrokenBusyboxException + * + */ + public String getFilePermissions(String file) throws BrokenBusyboxException, TimeoutException, + IOException { + Log.d(RootCommands.TAG, "Checking permissions for " + file); + + String permissions = null; + + if (fileExists(file)) { + Log.d(RootCommands.TAG, file + " was found."); + + LsCommand lsCommand = new LsCommand(file); + shell.add(lsCommand).waitForFinish(); + + permissions = lsCommand.getPermissions(); + } + + return permissions; + } + + /** + * Sets permission of file + * + * @param file + * absolute path to file + * @param permissions + * String like 777 + * @return true if command worked + * @throws BrokenBusyboxException + * @throws java.util.concurrent.TimeoutException + * @throws java.io.IOException + */ + public boolean setFilePermissions(String file, String permissions) + throws BrokenBusyboxException, TimeoutException, IOException { + Log.d(RootCommands.TAG, "Set permissions of " + file + " to " + permissions); + + SimpleCommand chmodCommand = new SimpleCommand("chmod " + permissions + " " + file); + shell.add(chmodCommand).waitForFinish(); + + if (chmodCommand.getExitCode() == 0) { + return true; + } else { + return false; + } + } + + /** + * This will return a String that represent the symlink for a specified file. + * + * @param file + * The path to the file to get the Symlink for. (must have absolute path) + * + * @return A String that represent the symlink for a specified file or null if no symlink + * exists. + * @throws java.io.IOException + * @throws java.util.concurrent.TimeoutException + * @throws BrokenBusyboxException + */ + public String getSymlink(String file) throws BrokenBusyboxException, TimeoutException, + IOException { + Log.d(RootCommands.TAG, "Find symlink for " + file); + + String symlink = null; + + LsCommand lsCommand = new LsCommand(file); + shell.add(lsCommand).waitForFinish(); + + symlink = lsCommand.getSymlink(); + + return symlink; + } + + /** + * Copys a file to a destination. Because cp is not available on all android devices, we use dd + * or cat. + * + * @param source + * example: /data/data/org.adaway/files/hosts + * @param destination + * example: /system/etc/hosts + * @param remountAsRw + * remounts the destination as read/write before writing to it + * @param preserveFileAttributes + * tries to copy file attributes from source to destination, if only cat is available + * only permissions are preserved + * @return true if it was successfully copied + * @throws BrokenBusyboxException + * @throws java.io.IOException + * @throws java.util.concurrent.TimeoutException + */ + public boolean copyFile(String source, String destination, boolean remountAsRw, + boolean preservePermissions) throws BrokenBusyboxException, IOException, + TimeoutException { + + /* + * dd can only copy files, but we can not check if the source is a file without invoking + * shell commands, because from Java we probably have no read access, thus we only check if + * they are ending with trailing slashes + */ + if (source.endsWith("/") || destination.endsWith("/")) { + throw new FileNotFoundException("dd can only copy files!"); + } + + // remount destination as read/write before copying to it + if (remountAsRw) { + if (!remount(destination, "RW")) { + Log.d(RootCommands.TAG, + "Remounting failed! There is probably no need to remount this partition!"); + } + } + + // get permissions of source before overwriting + String permissions = null; + if (preservePermissions) { + permissions = getFilePermissions(source); + } + + boolean commandSuccess = false; + + SimpleCommand ddCommand = new SimpleCommand("dd if=" + source + " of=" + + destination); + shell.add(ddCommand).waitForFinish(); + + if (ddCommand.getExitCode() == 0) { + commandSuccess = true; + } else { + // try cat if dd fails + SimpleCommand catCommand = new SimpleCommand("cat " + source + " > " + + destination); + shell.add(catCommand).waitForFinish(); + + if (catCommand.getExitCode() == 0) { + commandSuccess = true; + } + } + + // set back permissions from source to destination + if (preservePermissions) { + setFilePermissions(destination, permissions); + } + + // remount destination back to read only + if (remountAsRw) { + if (!remount(destination, "RO")) { + Log.d(RootCommands.TAG, + "Remounting failed! There is probably no need to remount this partition!"); + } + } + + return commandSuccess; + } + + public static final int REBOOT_HOTREBOOT = 1; + public static final int REBOOT_REBOOT = 2; + public static final int REBOOT_SHUTDOWN = 3; + public static final int REBOOT_RECOVERY = 4; + + /** + * Shutdown or reboot device. Possible actions are REBOOT_HOTREBOOT, REBOOT_REBOOT, + * REBOOT_SHUTDOWN, REBOOT_RECOVERY + * + * @param action + * @throws java.io.IOException + * @throws java.util.concurrent.TimeoutException + * @throws BrokenBusyboxException + */ + public void reboot(int action) throws BrokenBusyboxException, TimeoutException, IOException { + if (action == REBOOT_HOTREBOOT) { + killAll("system_server"); + // or: killAll("zygote"); + } else { + String command; + switch (action) { + case REBOOT_REBOOT: + command = "reboot"; + break; + case REBOOT_SHUTDOWN: + command = "reboot -p"; + break; + case REBOOT_RECOVERY: + command = "reboot recovery"; + break; + default: + command = "reboot"; + break; + } + + SimpleCommand rebootCommand = new SimpleCommand(command); + shell.add(rebootCommand).waitForFinish(); + + if (rebootCommand.getExitCode() == -1) { + Log.e(RootCommands.TAG, "Reboot failed!"); + } + } + } + + /** + * This command checks if a file exists + */ + private class FileExistsCommand extends Command { + private String file; + private boolean fileExists = false; + + public FileExistsCommand(String file) { + super("ls " + file); + this.file = file; + } + + public boolean isFileExists() { + return fileExists; + } + + @Override + public void output(int id, String line) { + if (line.trim().equals(file)) { + fileExists = true; + } + } + + @Override + public void afterExecution(int id, int exitCode) { + } + + } + + /** + * Use this to check whether or not a file exists on the filesystem. + * + * @param file + * String that represent the file, including the full path to the file and its name. + * + * @return a boolean that will indicate whether or not the file exists. + * @throws java.io.IOException + * @throws java.util.concurrent.TimeoutException + * @throws BrokenBusyboxException + * + */ + public boolean fileExists(String file) throws BrokenBusyboxException, TimeoutException, + IOException { + FileExistsCommand fileExistsCommand = new FileExistsCommand(file); + shell.add(fileExistsCommand).waitForFinish(); + + if (fileExistsCommand.isFileExists()) { + return true; + } else { + return false; + } + } + + public abstract class WithPermissions { + abstract void whileHavingPermissions(); + } + + /** + * Execute user defined Java code while having temporary permissions on a file + * + * @param file + * @param withPermissions + * @throws BrokenBusyboxException + * @throws java.util.concurrent.TimeoutException + * @throws java.io.IOException + */ + public void withPermission(String file, String permission, WithPermissions withPermissions) + throws BrokenBusyboxException, TimeoutException, IOException { + String oldPermissions = getFilePermissions(file); + + // set permissions (If set to 666, then Dalvik VM can also write to that file!) + setFilePermissions(file, permission); + + // execute user defined code + withPermissions.whileHavingPermissions(); + + // set back to old permissions + setFilePermissions(file, oldPermissions); + } + + /** + * Execute user defined Java code while having temporary write permissions on a file using chmod + * 666 + * + * @param file + * @param withWritePermissions + * @throws BrokenBusyboxException + * @throws java.util.concurrent.TimeoutException + * @throws java.io.IOException + */ + public void withWritePermissions(String file, WithPermissions withWritePermissions) + throws BrokenBusyboxException, TimeoutException, IOException { + withPermission(file, "666", withWritePermissions); + } + + /** + * Sets system clock using /dev/alarm + * + * @param millis + * @throws BrokenBusyboxException + * @throws java.util.concurrent.TimeoutException + * @throws java.io.IOException + */ + public void setSystemClock(final long millis) throws BrokenBusyboxException, TimeoutException, + IOException { + withWritePermissions("/dev/alarm", new WithPermissions() { + + @Override + void whileHavingPermissions() { + SystemClock.setCurrentTimeMillis(millis); + } + }); + } + + /** + * Adjust system clock by offset using /dev/alarm + * + * @param offset + * @throws BrokenBusyboxException + * @throws java.util.concurrent.TimeoutException + * @throws java.io.IOException + */ + public void adjustSystemClock(final long offset) throws BrokenBusyboxException, + TimeoutException, IOException { + withWritePermissions("/dev/alarm", new WithPermissions() { + + @Override + void whileHavingPermissions() { + SystemClock.setCurrentTimeMillis(System.currentTimeMillis() + offset); + } + }); + } + + /** + * This will take a path, which can contain the file name as well, and attempt to remount the + * underlying partition. + * + * For example, passing in the following string: + * "/system/bin/some/directory/that/really/would/never/exist" will result in /system ultimately + * being remounted. However, keep in mind that the longer the path you supply, the more work + * this has to do, and the slower it will run. + * + * @param file + * file path + * @param mountType + * mount type: pass in RO (Read only) or RW (Read Write) + * @return a boolean which indicates whether or not the partition has been + * remounted as specified. + */ + public boolean remount(String file, String mountType) { + // Recieved a request, get an instance of Remounter + Remounter remounter = new Remounter(shell); + // send the request + return (remounter.remount(file, mountType)); + } + + /** + * This will tell you how the specified mount is mounted. rw, ro, etc... + * + * @param The + * mount you want to check + * + * @return String What the mount is mounted as. + * @throws Exception + * if we cannot determine how the mount is mounted. + */ + public String getMountedAs(String path) throws Exception { + ArrayList mounts = Remounter.getMounts(); + if (mounts != null) { + for (Mount mount : mounts) { + if (path.contains(mount.getMountPoint().getAbsolutePath())) { + Log.d(RootCommands.TAG, (String) mount.getFlags().toArray()[0]); + return (String) mount.getFlags().toArray()[0]; + } + } + + throw new Exception(); + } else { + throw new Exception(); + } + } + + /** + * Check if there is enough space on partition where target is located + * + * @param size + * size of file to put on partition + * @param target + * path where to put the file + * + * @return true if it will fit on partition of target, false if it will not fit. + */ + public boolean hasEnoughSpaceOnPartition(String target, long size) { + try { + // new File(target).getFreeSpace() (API 9) is not working on data partition + + // get directory without file + String directory = new File(target).getParent().toString(); + + StatFs stat = new StatFs(directory); + long blockSize = stat.getBlockSize(); + long availableBlocks = stat.getAvailableBlocks(); + long availableSpace = availableBlocks * blockSize; + + Log.i(RootCommands.TAG, "Checking for enough space: Target: " + target + + ", directory: " + directory + " size: " + size + ", availableSpace: " + + availableSpace); + + if (size < availableSpace) { + return true; + } else { + Log.e(RootCommands.TAG, "Not enough space on partition!"); + return false; + } + } catch (Exception e) { + // if new StatFs(directory) fails catch IllegalArgumentException and just return true as + // workaround + Log.e(RootCommands.TAG, "Problem while getting available space on partition!", e); + return true; + } + } + + /** + * TODO: Not tested! + * + * @param toggle + * @throws java.io.IOException + * @throws java.util.concurrent.TimeoutException + * @throws BrokenBusyboxException + */ + public void toggleAdbDaemon(boolean toggle) throws BrokenBusyboxException, TimeoutException, + IOException { + SimpleCommand disableAdb = new SimpleCommand("setprop persist.service.adb.enable 0", + "stop adbd"); + SimpleCommand enableAdb = new SimpleCommand("setprop persist.service.adb.enable 1", + "stop adbd", "sleep 1", "start adbd"); + + if (toggle) { + shell.add(enableAdb).waitForFinish(); + } else { + shell.add(disableAdb).waitForFinish(); + } + } + +} diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/Command.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/Command.java index 9887e57..488cbae 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/Command.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/Command.java @@ -1,155 +1,155 @@ - - -package org.sufficientlysecure.rootcommands.command; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.concurrent.TimeoutException; - -import org.sufficientlysecure.rootcommands.RootCommands; -import org.sufficientlysecure.rootcommands.Shell; -import org.sufficientlysecure.rootcommands.util.BrokenBusyboxException; -import org.sufficientlysecure.rootcommands.util.Log; - -public abstract class Command { - final String command[]; - boolean finished = false; - boolean brokenBusyboxDetected = false; - int exitCode; - int id; - int timeout = RootCommands.DEFAULT_TIMEOUT; - Shell shell = null; - - public Command(String... command) { - this.command = command; - } - - public Command(int timeout, String... command) { - this.command = command; - this.timeout = timeout; - } - - /** - * This is called from Shell after adding it - * - * @param shell - * @param id - */ - public void addedToShell(Shell shell, int id) { - this.shell = shell; - this.id = id; - } - - /** - * Gets command string executed on the shell - * - * @return - */ - public String getCommand() { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < command.length; i++) { - // redirect stderr to stdout - sb.append(command[i] + " 2>&1"); - sb.append('\n'); - } - Log.d(RootCommands.TAG, "Sending command(s): " + sb.toString()); - return sb.toString(); - } - - public void writeCommand(OutputStream out) throws IOException { - out.write(getCommand().getBytes()); - } - - public void processOutput(String line) { - Log.d(RootCommands.TAG, "ID: " + id + ", Output: " + line); - - /* - * Try to detect broken toolbox/busybox binaries (see - * https://code.google.com/p/busybox-android/issues/detail?id=1) - * - * It is giving "Value too large for defined data type" on certain file operations (e.g. ls - * and chown) in certain directories (e.g. /data/data) - */ - if (line.contains("Value too large for defined data type")) { - Log.e(RootCommands.TAG, "Busybox is broken with high probability due to line: " + line); - brokenBusyboxDetected = true; - } - - // now execute specific output parsing - output(id, line); - } - - public abstract void output(int id, String line); - - public void processAfterExecution(int exitCode) { - Log.d(RootCommands.TAG, "ID: " + id + ", ExitCode: " + exitCode); - - afterExecution(id, exitCode); - } - - public abstract void afterExecution(int id, int exitCode); - - public void commandFinished(int id) { - Log.d(RootCommands.TAG, "Command " + id + " finished."); - } - - public void setExitCode(int code) { - synchronized (this) { - exitCode = code; - finished = true; - commandFinished(id); - this.notifyAll(); - } - } - - /** - * Close the shell - * - * @param reason - */ - public void terminate(String reason) { - try { - shell.close(); - Log.d(RootCommands.TAG, "Terminating the shell."); - terminated(reason); - } catch (IOException e) { - } - } - - public void terminated(String reason) { - setExitCode(-1); - Log.d(RootCommands.TAG, "Command " + id + " did not finish, because of " + reason); - } - - /** - * Waits for this command to finish and forwards exitCode into afterExecution method - * - * @param timeout - * @throws java.util.concurrent.TimeoutException - * @throws BrokenBusyboxException - */ - public void waitForFinish() throws TimeoutException, BrokenBusyboxException { - synchronized (this) { - while (!finished) { - try { - this.wait(timeout); - } catch (InterruptedException e) { - Log.e(RootCommands.TAG, "InterruptedException in waitForFinish()", e); - } - - if (!finished) { - finished = true; - terminate("Timeout"); - throw new TimeoutException("Timeout has occurred."); - } - } - - if (brokenBusyboxDetected) { - throw new BrokenBusyboxException(); - } - - processAfterExecution(exitCode); - } - } - + + +package org.sufficientlysecure.rootcommands.command; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.concurrent.TimeoutException; + +import org.sufficientlysecure.rootcommands.RootCommands; +import org.sufficientlysecure.rootcommands.Shell; +import org.sufficientlysecure.rootcommands.util.BrokenBusyboxException; +import org.sufficientlysecure.rootcommands.util.Log; + +public abstract class Command { + final String command[]; + boolean finished = false; + boolean brokenBusyboxDetected = false; + int exitCode; + int id; + int timeout = RootCommands.DEFAULT_TIMEOUT; + Shell shell = null; + + public Command(String... command) { + this.command = command; + } + + public Command(int timeout, String... command) { + this.command = command; + this.timeout = timeout; + } + + /** + * This is called from Shell after adding it + * + * @param shell + * @param id + */ + public void addedToShell(Shell shell, int id) { + this.shell = shell; + this.id = id; + } + + /** + * Gets command string executed on the shell + * + * @return + */ + public String getCommand() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < command.length; i++) { + // redirect stderr to stdout + sb.append(command[i] + " 2>&1"); + sb.append('\n'); + } + Log.d(RootCommands.TAG, "Sending command(s): " + sb.toString()); + return sb.toString(); + } + + public void writeCommand(OutputStream out) throws IOException { + out.write(getCommand().getBytes()); + } + + public void processOutput(String line) { + Log.d(RootCommands.TAG, "ID: " + id + ", Output: " + line); + + /* + * Try to detect broken toolbox/busybox binaries (see + * https://code.google.com/p/busybox-android/issues/detail?id=1) + * + * It is giving "Value too large for defined data type" on certain file operations (e.g. ls + * and chown) in certain directories (e.g. /data/data) + */ + if (line.contains("Value too large for defined data type")) { + Log.e(RootCommands.TAG, "Busybox is broken with high probability due to line: " + line); + brokenBusyboxDetected = true; + } + + // now execute specific output parsing + output(id, line); + } + + public abstract void output(int id, String line); + + public void processAfterExecution(int exitCode) { + Log.d(RootCommands.TAG, "ID: " + id + ", ExitCode: " + exitCode); + + afterExecution(id, exitCode); + } + + public abstract void afterExecution(int id, int exitCode); + + public void commandFinished(int id) { + Log.d(RootCommands.TAG, "Command " + id + " finished."); + } + + public void setExitCode(int code) { + synchronized (this) { + exitCode = code; + finished = true; + commandFinished(id); + this.notifyAll(); + } + } + + /** + * Close the shell + * + * @param reason + */ + public void terminate(String reason) { + try { + shell.close(); + Log.d(RootCommands.TAG, "Terminating the shell."); + terminated(reason); + } catch (IOException e) { + } + } + + public void terminated(String reason) { + setExitCode(-1); + Log.d(RootCommands.TAG, "Command " + id + " did not finish, because of " + reason); + } + + /** + * Waits for this command to finish and forwards exitCode into afterExecution method + * + * @param timeout + * @throws java.util.concurrent.TimeoutException + * @throws BrokenBusyboxException + */ + public void waitForFinish() throws TimeoutException, BrokenBusyboxException { + synchronized (this) { + while (!finished) { + try { + this.wait(timeout); + } catch (InterruptedException e) { + Log.e(RootCommands.TAG, "InterruptedException in waitForFinish()", e); + } + + if (!finished) { + finished = true; + terminate("Timeout"); + throw new TimeoutException("Timeout has occurred."); + } + } + + if (brokenBusyboxDetected) { + throw new BrokenBusyboxException(); + } + + processAfterExecution(exitCode); + } + } + } \ No newline at end of file diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/ExecutableCommand.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/ExecutableCommand.java index 1cd2a95..0bd92d7 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/ExecutableCommand.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/ExecutableCommand.java @@ -1,51 +1,51 @@ - - -package org.sufficientlysecure.rootcommands.command; - -import java.io.File; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.os.Build; - -public abstract class ExecutableCommand extends Command { - public static final String EXECUTABLE_PREFIX = "lib"; - public static final String EXECUTABLE_SUFFIX = "_exec.so"; - - /** - * This class provides a way to use your own binaries! - * - * Include your own executables, renamed from * to lib*_exec.so, in your libs folder under the - * architecture directories. Now they will be deployed by Android the same way libraries are - * deployed! - * - * See README for more information how to use your own executables! - * - * @param context - * @param executableName - * @param parameters - */ - public ExecutableCommand(Context context, String executableName, String parameters) { - super(getLibDirectory(context) + File.separator + EXECUTABLE_PREFIX + executableName - + EXECUTABLE_SUFFIX + " " + parameters); - } - - /** - * Get full path to lib directory of app - * - * @return dir as String - */ - @SuppressLint("NewApi") - private static String getLibDirectory(Context context) { - if (Build.VERSION.SDK_INT >= 9) { - return context.getApplicationInfo().nativeLibraryDir; - } else { - return context.getApplicationInfo().dataDir + File.separator + "lib"; - } - } - - public abstract void output(int id, String line); - - public abstract void afterExecution(int id, int exitCode); - + + +package org.sufficientlysecure.rootcommands.command; + +import java.io.File; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Build; + +public abstract class ExecutableCommand extends Command { + public static final String EXECUTABLE_PREFIX = "lib"; + public static final String EXECUTABLE_SUFFIX = "_exec.so"; + + /** + * This class provides a way to use your own binaries! + * + * Include your own executables, renamed from * to lib*_exec.so, in your libs folder under the + * architecture directories. Now they will be deployed by Android the same way libraries are + * deployed! + * + * See README for more information how to use your own executables! + * + * @param context + * @param executableName + * @param parameters + */ + public ExecutableCommand(Context context, String executableName, String parameters) { + super(getLibDirectory(context) + File.separator + EXECUTABLE_PREFIX + executableName + + EXECUTABLE_SUFFIX + " " + parameters); + } + + /** + * Get full path to lib directory of app + * + * @return dir as String + */ + @SuppressLint("NewApi") + private static String getLibDirectory(Context context) { + if (Build.VERSION.SDK_INT >= 9) { + return context.getApplicationInfo().nativeLibraryDir; + } else { + return context.getApplicationInfo().dataDir + File.separator + "lib"; + } + } + + public abstract void output(int id, String line); + + public abstract void afterExecution(int id, int exitCode); + } \ No newline at end of file diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleCommand.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleCommand.java index 8f11c05..b2091c8 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleCommand.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleCommand.java @@ -1,29 +1,29 @@ - - -package org.sufficientlysecure.rootcommands.command; - -public class SimpleCommand extends Command { - private StringBuilder sb = new StringBuilder(); - - public SimpleCommand(String... command) { - super(command); - } - - @Override - public void output(int id, String line) { - sb.append(line).append('\n'); - } - - @Override - public void afterExecution(int id, int exitCode) { - } - - public String getOutput() { - return sb.toString(); - } - - public int getExitCode() { - return exitCode; - } - + + +package org.sufficientlysecure.rootcommands.command; + +public class SimpleCommand extends Command { + private StringBuilder sb = new StringBuilder(); + + public SimpleCommand(String... command) { + super(command); + } + + @Override + public void output(int id, String line) { + sb.append(line).append('\n'); + } + + @Override + public void afterExecution(int id, int exitCode) { + } + + public String getOutput() { + return sb.toString(); + } + + public int getExitCode() { + return exitCode; + } + } \ No newline at end of file diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleExecutableCommand.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleExecutableCommand.java index 1ead418..78fd2be 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleExecutableCommand.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleExecutableCommand.java @@ -1,31 +1,31 @@ - - -package org.sufficientlysecure.rootcommands.command; - -import android.content.Context; - -public class SimpleExecutableCommand extends ExecutableCommand { - private StringBuilder sb = new StringBuilder(); - - public SimpleExecutableCommand(Context context, String executableName, String parameters) { - super(context, executableName, parameters); - } - - @Override - public void output(int id, String line) { - sb.append(line).append('\n'); - } - - @Override - public void afterExecution(int id, int exitCode) { - } - - public String getOutput() { - return sb.toString(); - } - - public int getExitCode() { - return exitCode; - } - + + +package org.sufficientlysecure.rootcommands.command; + +import android.content.Context; + +public class SimpleExecutableCommand extends ExecutableCommand { + private StringBuilder sb = new StringBuilder(); + + public SimpleExecutableCommand(Context context, String executableName, String parameters) { + super(context, executableName, parameters); + } + + @Override + public void output(int id, String line) { + sb.append(line).append('\n'); + } + + @Override + public void afterExecution(int id, int exitCode) { + } + + public String getOutput() { + return sb.toString(); + } + + public int getExitCode() { + return exitCode; + } + } \ No newline at end of file diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/BrokenBusyboxException.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/BrokenBusyboxException.java index 579518d..bf40bf4 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/BrokenBusyboxException.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/BrokenBusyboxException.java @@ -1,18 +1,18 @@ - - -package org.sufficientlysecure.rootcommands.util; - -import java.io.IOException; - -public class BrokenBusyboxException extends IOException { - private static final long serialVersionUID = 8337358201589488409L; - - public BrokenBusyboxException() { - super(); - } - - public BrokenBusyboxException(String detailMessage) { - super(detailMessage); - } - -} + + +package org.sufficientlysecure.rootcommands.util; + +import java.io.IOException; + +public class BrokenBusyboxException extends IOException { + private static final long serialVersionUID = 8337358201589488409L; + + public BrokenBusyboxException() { + super(); + } + + public BrokenBusyboxException(String detailMessage) { + super(detailMessage); + } + +} diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/Log.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/Log.java index a9a9cb7..e55da98 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/Log.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/Log.java @@ -1,69 +1,69 @@ - - -package org.sufficientlysecure.rootcommands.util; - -import org.sufficientlysecure.rootcommands.RootCommands; - -/** - * Wraps Android Logging to enable or disable debug output using Constants - * - */ -public final class Log { - - public static void v(String tag, String msg) { - if (RootCommands.DEBUG) { - android.util.Log.v(tag, msg); - } - } - - public static void v(String tag, String msg, Throwable tr) { - if (RootCommands.DEBUG) { - android.util.Log.v(tag, msg, tr); - } - } - - public static void d(String tag, String msg) { - if (RootCommands.DEBUG) { - android.util.Log.d(tag, msg); - } - } - - public static void d(String tag, String msg, Throwable tr) { - if (RootCommands.DEBUG) { - android.util.Log.d(tag, msg, tr); - } - } - - public static void i(String tag, String msg) { - if (RootCommands.DEBUG) { - android.util.Log.i(tag, msg); - } - } - - public static void i(String tag, String msg, Throwable tr) { - if (RootCommands.DEBUG) { - android.util.Log.i(tag, msg, tr); - } - } - - public static void w(String tag, String msg) { - android.util.Log.w(tag, msg); - } - - public static void w(String tag, String msg, Throwable tr) { - android.util.Log.w(tag, msg, tr); - } - - public static void w(String tag, Throwable tr) { - android.util.Log.w(tag, tr); - } - - public static void e(String tag, String msg) { - android.util.Log.e(tag, msg); - } - - public static void e(String tag, String msg, Throwable tr) { - android.util.Log.e(tag, msg, tr); - } - -} + + +package org.sufficientlysecure.rootcommands.util; + +import org.sufficientlysecure.rootcommands.RootCommands; + +/** + * Wraps Android Logging to enable or disable debug output using Constants + * + */ +public final class Log { + + public static void v(String tag, String msg) { + if (RootCommands.DEBUG) { + android.util.Log.v(tag, msg); + } + } + + public static void v(String tag, String msg, Throwable tr) { + if (RootCommands.DEBUG) { + android.util.Log.v(tag, msg, tr); + } + } + + public static void d(String tag, String msg) { + if (RootCommands.DEBUG) { + android.util.Log.d(tag, msg); + } + } + + public static void d(String tag, String msg, Throwable tr) { + if (RootCommands.DEBUG) { + android.util.Log.d(tag, msg, tr); + } + } + + public static void i(String tag, String msg) { + if (RootCommands.DEBUG) { + android.util.Log.i(tag, msg); + } + } + + public static void i(String tag, String msg, Throwable tr) { + if (RootCommands.DEBUG) { + android.util.Log.i(tag, msg, tr); + } + } + + public static void w(String tag, String msg) { + android.util.Log.w(tag, msg); + } + + public static void w(String tag, String msg, Throwable tr) { + android.util.Log.w(tag, msg, tr); + } + + public static void w(String tag, Throwable tr) { + android.util.Log.w(tag, tr); + } + + public static void e(String tag, String msg) { + android.util.Log.e(tag, msg); + } + + public static void e(String tag, String msg, Throwable tr) { + android.util.Log.e(tag, msg, tr); + } + +} diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/RootAccessDeniedException.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/RootAccessDeniedException.java index 1520a5b..650f1ed 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/RootAccessDeniedException.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/RootAccessDeniedException.java @@ -1,18 +1,18 @@ - - -package org.sufficientlysecure.rootcommands.util; - -import java.io.IOException; - -public class RootAccessDeniedException extends IOException { - private static final long serialVersionUID = 9088998884166225540L; - - public RootAccessDeniedException() { - super(); - } - - public RootAccessDeniedException(String detailMessage) { - super(detailMessage); - } - -} + + +package org.sufficientlysecure.rootcommands.util; + +import java.io.IOException; + +public class RootAccessDeniedException extends IOException { + private static final long serialVersionUID = 9088998884166225540L; + + public RootAccessDeniedException() { + super(); + } + + public RootAccessDeniedException(String detailMessage) { + super(detailMessage); + } + +} diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/UnsupportedArchitectureException.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/UnsupportedArchitectureException.java index 4124d9b..e8535d2 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/UnsupportedArchitectureException.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/UnsupportedArchitectureException.java @@ -1,16 +1,16 @@ - - -package org.sufficientlysecure.rootcommands.util; - -public class UnsupportedArchitectureException extends Exception { - private static final long serialVersionUID = 7826528799780001655L; - - public UnsupportedArchitectureException() { - super(); - } - - public UnsupportedArchitectureException(String detailMessage) { - super(detailMessage); - } - -} + + +package org.sufficientlysecure.rootcommands.util; + +public class UnsupportedArchitectureException extends Exception { + private static final long serialVersionUID = 7826528799780001655L; + + public UnsupportedArchitectureException() { + super(); + } + + public UnsupportedArchitectureException(String detailMessage) { + super(detailMessage); + } + +} diff --git a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/Utils.java b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/Utils.java index 98d90d1..e9a382f 100644 --- a/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/Utils.java +++ b/libraries/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/Utils.java @@ -1,89 +1,89 @@ - - -package org.sufficientlysecure.rootcommands.util; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Map; - -import org.sufficientlysecure.rootcommands.RootCommands; - -public class Utils { - /* - * The emulator and ADP1 device both have a su binary in /system/xbin/su, but it doesn't allow - * apps to use it (su app_29 $ su su: uid 10029 not allowed to su). - * - * Cyanogen used to have su in /system/bin/su, in newer versions it's a symlink to - * /system/xbin/su. - * - * The Archos tablet has it in /data/bin/su, since they don't have write access to /system yet. - */ - static final String[] BinaryPlaces = { "/data/bin/", "/system/bin/", "/system/xbin/", "/sbin/", - "/data/local/xbin/", "/data/local/bin/", "/system/sd/xbin/", "/system/bin/failsafe/", - "/data/local/" }; - - /** - * Determine the path of the su executable. - * - * Code from https://github.com/miracle2k/android-autostarts, use under Apache License was - * agreed by Michael Elsdörfer - */ - public static String getSuPath() { - for (String p : BinaryPlaces) { - File su = new File(p + "su"); - if (su.exists()) { - Log.d(RootCommands.TAG, "su found at: " + p); - return su.getAbsolutePath(); - } else { - Log.v(RootCommands.TAG, "No su in: " + p); - } - } - Log.d(RootCommands.TAG, "No su found in a well-known location, " + "will just use \"su\"."); - return "su"; - } - - /** - * This code is adapted from java.lang.ProcessBuilder.start(). - * - * The problem is that Android doesn't allow us to modify the map returned by - * ProcessBuilder.environment(), even though the docstring indicates that it should. This is - * because it simply returns the SystemEnvironment object that System.getenv() gives us. The - * relevant portion in the source code is marked as "// android changed", so presumably it's not - * the case in the original version of the Apache Harmony project. - * - * Note that simply passing the environment variables we want to Process.exec won't be good - * enough, since that would override the environment we inherited completely. - * - * We needed to be able to set a CLASSPATH environment variable for our new process in order to - * use the "app_process" command directly. Note: "app_process" takes arguments passed on to the - * Dalvik VM as well; this might be an alternative way to set the class path. - * - * Code from https://github.com/miracle2k/android-autostarts, use under Apache License was - * agreed by Michael Elsdörfer - */ - public static Process runWithEnv(String command, ArrayList customAddedEnv, - String baseDirectory) throws IOException { - - Map environment = System.getenv(); - String[] envArray = new String[environment.size() - + (customAddedEnv != null ? customAddedEnv.size() : 0)]; - int i = 0; - for (Map.Entry entry : environment.entrySet()) { - envArray[i++] = entry.getKey() + "=" + entry.getValue(); - } - if (customAddedEnv != null) { - for (String entry : customAddedEnv) { - envArray[i++] = entry; - } - } - - Process process; - if (baseDirectory == null) { - process = Runtime.getRuntime().exec(command, envArray, null); - } else { - process = Runtime.getRuntime().exec(command, envArray, new File(baseDirectory)); - } - return process; - } -} + + +package org.sufficientlysecure.rootcommands.util; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Map; + +import org.sufficientlysecure.rootcommands.RootCommands; + +public class Utils { + /* + * The emulator and ADP1 device both have a su binary in /system/xbin/su, but it doesn't allow + * apps to use it (su app_29 $ su su: uid 10029 not allowed to su). + * + * Cyanogen used to have su in /system/bin/su, in newer versions it's a symlink to + * /system/xbin/su. + * + * The Archos tablet has it in /data/bin/su, since they don't have write access to /system yet. + */ + static final String[] BinaryPlaces = { "/data/bin/", "/system/bin/", "/system/xbin/", "/sbin/", + "/data/local/xbin/", "/data/local/bin/", "/system/sd/xbin/", "/system/bin/failsafe/", + "/data/local/" }; + + /** + * Determine the path of the su executable. + * + * Code from https://github.com/miracle2k/android-autostarts, use under Apache License was + * agreed by Michael Elsdörfer + */ + public static String getSuPath() { + for (String p : BinaryPlaces) { + File su = new File(p + "su"); + if (su.exists()) { + Log.d(RootCommands.TAG, "su found at: " + p); + return su.getAbsolutePath(); + } else { + Log.v(RootCommands.TAG, "No su in: " + p); + } + } + Log.d(RootCommands.TAG, "No su found in a well-known location, " + "will just use \"su\"."); + return "su"; + } + + /** + * This code is adapted from java.lang.ProcessBuilder.start(). + * + * The problem is that Android doesn't allow us to modify the map returned by + * ProcessBuilder.environment(), even though the docstring indicates that it should. This is + * because it simply returns the SystemEnvironment object that System.getenv() gives us. The + * relevant portion in the source code is marked as "// android changed", so presumably it's not + * the case in the original version of the Apache Harmony project. + * + * Note that simply passing the environment variables we want to Process.exec won't be good + * enough, since that would override the environment we inherited completely. + * + * We needed to be able to set a CLASSPATH environment variable for our new process in order to + * use the "app_process" command directly. Note: "app_process" takes arguments passed on to the + * Dalvik VM as well; this might be an alternative way to set the class path. + * + * Code from https://github.com/miracle2k/android-autostarts, use under Apache License was + * agreed by Michael Elsdörfer + */ + public static Process runWithEnv(String command, ArrayList customAddedEnv, + String baseDirectory) throws IOException { + + Map environment = System.getenv(); + String[] envArray = new String[environment.size() + + (customAddedEnv != null ? customAddedEnv.size() : 0)]; + int i = 0; + for (Map.Entry entry : environment.entrySet()) { + envArray[i++] = entry.getKey() + "=" + entry.getValue(); + } + if (customAddedEnv != null) { + for (String entry : customAddedEnv) { + envArray[i++] = entry; + } + } + + Process process; + if (baseDirectory == null) { + process = Runtime.getRuntime().exec(command, envArray, null); + } else { + process = Runtime.getRuntime().exec(command, envArray, new File(baseDirectory)); + } + return process; + } +} diff --git a/libraries/sharedCode/.gitignore b/libraries/sharedCode/.gitignore index 796b96d..3543521 100644 --- a/libraries/sharedCode/.gitignore +++ b/libraries/sharedCode/.gitignore @@ -1 +1 @@ -/build +/build diff --git a/libraries/sharedCode/build.gradle b/libraries/sharedCode/build.gradle index e15a501..d87b778 100644 --- a/libraries/sharedCode/build.gradle +++ b/libraries/sharedCode/build.gradle @@ -1,78 +1,77 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - - - -apply plugin: 'com.android.library' - -android { - lintOptions { - disable 'MissingTranslation', 'ExtraTranslation' - } - - compileSdkVersion 21 - buildToolsVersion '21.0.2' - - defaultConfig { - applicationId "sharedcode.turboeditor" - minSdkVersion 11 - targetSdkVersion 21 - versionCode 1 - versionName "1.0" - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - buildTypes { - release { - runProguard false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - lintOptions { - abortOnError false - } - - packagingOptions { - exclude 'META-INF/LICENSE.txt' - exclude 'META-INF/NOTICE.txt' - } -} - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile project(':libraries:RootCommands') - compile project(':libraries:FloatingActionButton') - //compile('de.greenrobot:eventbus:2.2.1') { - // exclude module: 'support-v4' - // } - // compile 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3' - compile 'org.apache.commons:commons-lang3:3.1' - compile files('libs/juniversalchardet-1.0.3.jar') - compile ("com.android.support:appcompat-v7:21.+") { - exclude group: 'com.android.support', module: 'support-v4' - } - compile 'com.android.support:support-v4:21.+' - compile 'com.github.gabrielemariotti.changeloglib:library:1.5.1' - compile 'commons-io:commons-io:2.4' - compile 'com.android.support:support-annotations:20.0.0' -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + + + +apply plugin: 'com.android.library' + +android { + lintOptions { + disable 'MissingTranslation', 'ExtraTranslation' + } + + compileSdkVersion 21 + buildToolsVersion '21.0.2' + + defaultConfig { + applicationId "sharedcode.turboeditor" + minSdkVersion 11 + targetSdkVersion 21 + versionCode 1 + versionName "1.0" + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + buildTypes { + release { + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + lintOptions { + abortOnError false + } + + packagingOptions { + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/NOTICE.txt' + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile project(':libraries:RootCommands') + compile project(':libraries:FloatingActionButton') + //compile('de.greenrobot:eventbus:2.2.1') { + // exclude module: 'support-v4' + // } + // compile 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3' + compile 'org.apache.commons:commons-lang3:3.1' + compile files('libs/juniversalchardet-1.0.3.jar') + compile ("com.android.support:appcompat-v7:21.+") { + exclude group: 'com.android.support', module: 'support-v4' + } + compile 'com.android.support:support-v4:21.+' + compile 'com.github.gabrielemariotti.changeloglib:library:1.5.1' + compile 'commons-io:commons-io:2.4' + compile 'com.android.support:support-annotations:20.0.0' +} diff --git a/libraries/sharedCode/proguard-rules.pro b/libraries/sharedCode/proguard-rules.pro index 9f604d1..a946ab9 100644 --- a/libraries/sharedCode/proguard-rules.pro +++ b/libraries/sharedCode/proguard-rules.pro @@ -1,17 +1,17 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in C:/Users/Vlad/AppData/Local/Android/android-sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# 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 *; -#} +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:/Users/Vlad/AppData/Local/Android/android-sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# 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 *; +#} diff --git a/libraries/sharedCode/src/androidTest/java/sharedcode/turboeditor/ApplicationTest.java b/libraries/sharedCode/src/androidTest/java/sharedcode/turboeditor/ApplicationTest.java index 8a646ed..a195b1c 100644 --- a/libraries/sharedCode/src/androidTest/java/sharedcode/turboeditor/ApplicationTest.java +++ b/libraries/sharedCode/src/androidTest/java/sharedcode/turboeditor/ApplicationTest.java @@ -1,32 +1,32 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/AndroidManifest.xml b/libraries/sharedCode/src/main/AndroidManifest.xml index ee4199c..da3a89d 100644 --- a/libraries/sharedCode/src/main/AndroidManifest.xml +++ b/libraries/sharedCode/src/main/AndroidManifest.xml @@ -1,23 +1,23 @@ - - - - - + + + + + diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/MainActivity.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/MainActivity.java index 132b5e5..a4dbfd0 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/MainActivity.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/MainActivity.java @@ -1,2124 +1,2120 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.activity; - -import android.app.ProgressDialog; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Typeface; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.preference.PreferenceManager; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.view.MenuItemCompat; -import android.support.v7.app.ActionBarActivity; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.widget.ShareActionProvider; -import android.support.v7.widget.Toolbar; -import android.text.Editable; -import android.text.InputType; -import android.text.Selection; -import android.text.Spannable; -import android.text.TextPaint; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.text.method.KeyListener; -import android.text.style.ForegroundColorSpan; -import android.text.style.UnderlineSpan; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; -import android.widget.EditText; -import android.widget.HorizontalScrollView; -import android.widget.ListView; -import android.widget.Toast; - -import com.faizmalkani.floatingactionbutton.FloatingActionButton; - -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang3.ArrayUtils; -import org.sufficientlysecure.rootcommands.Shell; -import org.sufficientlysecure.rootcommands.Toolbox; - -import java.io.File; -import java.io.UnsupportedEncodingException; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.adapter.AdapterDrawer; -import sharedcode.turboeditor.dialogfragment.ChangelogDialog; -import sharedcode.turboeditor.dialogfragment.FileInfoDialog; -import sharedcode.turboeditor.dialogfragment.FindTextDialog; -import sharedcode.turboeditor.dialogfragment.NewFileDetailsDialog; -import sharedcode.turboeditor.dialogfragment.NumberPickerDialog; -import sharedcode.turboeditor.dialogfragment.SaveFileDialog; -import sharedcode.turboeditor.preferences.PreferenceHelper; -import sharedcode.turboeditor.task.SaveFileTask; -import sharedcode.turboeditor.texteditor.EditTextPadding; -import sharedcode.turboeditor.texteditor.FileUtils; -import sharedcode.turboeditor.texteditor.LineUtils; -import sharedcode.turboeditor.texteditor.PageSystem; -import sharedcode.turboeditor.texteditor.PageSystemButtons; -import sharedcode.turboeditor.texteditor.Patterns; -import sharedcode.turboeditor.texteditor.SearchResult; -import sharedcode.turboeditor.util.AccessStorageApi; -import sharedcode.turboeditor.util.AnimationUtils; -import sharedcode.turboeditor.util.AppInfoHelper; -import sharedcode.turboeditor.util.EventBusEvents; -import sharedcode.turboeditor.util.MimeTypes; -import sharedcode.turboeditor.util.ProCheckUtils; -import sharedcode.turboeditor.util.ThemeUtils; -import sharedcode.turboeditor.views.CustomDrawerLayout; -import sharedcode.turboeditor.views.DialogHelper; -import sharedcode.turboeditor.views.GoodScrollView; - -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.ENCODING; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.FONT_SIZE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.LINE_NUMERS; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.MONOSPACE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.READ_ONLY; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.SYNTAX; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.TEXT_SUGGESTIONS; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.WRAP_CONTENT; - -public abstract class MainActivity extends ActionBarActivity implements FindTextDialog - .SearchDialogInterface, GoodScrollView.ScrollInterface, PageSystem.PageSystemInterface, - PageSystemButtons.PageButtonsInterface, NumberPickerDialog.INumberPickerDialog, SaveFileDialog.ISaveDialog, - AdapterView.OnItemClickListener, AdapterDrawer.Callbacks{ - - //region VARIABLES - private static final int - ID_SELECT_ALL = android.R.id.selectAll; - private static final int ID_CUT = android.R.id.cut; - private static final int ID_COPY = android.R.id.copy; - private static final int ID_PASTE = android.R.id.paste; - private static final int SELECT_FILE_CODE = 121; - private static final int KITKAT_OPEN_REQUEST_CODE = 41; - private static final int SYNTAX_DELAY_MILLIS_SHORT = 250; - private static final int SYNTAX_DELAY_MILLIS_LONG = 1500; - private static final int ID_UNDO = R.id.im_undo; - private static final int ID_REDO = R.id.im_redo; - private static final int CHARS_TO_COLOR = 2500; - private static final Handler updateHandler = new Handler(); - private static final Runnable colorRunnable_duringEditing = - new Runnable() { - @Override - public void run() { - mEditor.replaceTextKeepCursor(null, true); - } - }; - private static final Runnable colorRunnable_duringScroll = - new Runnable() { - @Override - public void run() { - mEditor.replaceTextKeepCursor(null, false); - } - }; - private static boolean fileOpened = false; - private static String fileExtension; - /* - * This class provides a handy way to tie together the functionality of - * {@link DrawerLayout} and the framework ActionBar to implement the recommended - * design for navigation drawers. - */ - private static ActionBarDrawerToggle mDrawerToggle; - /* - * The Drawer Layout - */ - private static CustomDrawerLayout mDrawerLayout; - private static GoodScrollView verticalScroll; - private static String sFilePath = ""; - private static Editor mEditor; - private static HorizontalScrollView horizontalScroll; - private boolean searchingText; - private static SearchResult searchResult; - private static PageSystem pageSystem; - private static PageSystemButtons pageSystemButtons; - private static String currentEncoding = "UTF-8"; - private static Toolbar toolbar; - - /* - Navigation Drawer - */ - private static AdapterDrawer arrayAdapter; - private static LinkedList files; - //endregion - - //region Activity facts - - @Override - protected void onCreate(Bundle savedInstanceState) { - // set the windows background - ThemeUtils.setWindowsBackground(this); - // super!! - super.onCreate(savedInstanceState); - // setup the layout - setContentView(R.layout.activity_home); - toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar); - setSupportActionBar(toolbar); - // setup the navigation drawer - setupNavigationDrawer(); - // reset text editor - setupTextEditor(); - hideTextEditor(); - /* First Time we open this activity */ - if (savedInstanceState == null) { - // Open - mDrawerLayout.openDrawer(Gravity.START); - // Set the default title - getSupportActionBar().setTitle(getString(R.string.nome_app_turbo_editor)); - } - // parse the intent - parseIntent(getIntent()); - // show a dialog with the changelog - showChangeLog(); - } - - - @Override - protected final void onPostCreate(Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - mDrawerToggle.syncState(); - } - - @Override - public void onResume() { - super.onResume(); - // Refresh the list view - refreshList(); - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - parseIntent(intent); - } - - @Override - public void onPause() { - super.onPause(); - - if (PreferenceHelper.getAutoSave(getBaseContext()) && mEditor.canSaveFile()) { - saveTheFile(); - mEditor.fileSaved(); // so it doesn't ask to save in onDetach - } - } - - @Override - protected void onDestroy() { - try { - closeKeyBoard(); - } catch (NullPointerException e) { - e.printStackTrace(); - } - super.onDestroy(); - } - - @Override - public final void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - mDrawerToggle.onConfigurationChanged(newConfig); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - - if (keyCode == KeyEvent.KEYCODE_BACK) { - onBackPressed(); - return true; - } else if (keyCode == KeyEvent.KEYCODE_MENU) { - return false; - } else { - if (mEditor == null) - mEditor = (Editor) findViewById(R.id.editor); - - // this will happen on first key pressed on hard-keyboard only. Once myInputField - // gets the focus again, it will automatically receive further key presses. - - try { - if (fileOpened && mEditor != null && !mEditor.hasFocus()) { - mEditor.requestFocus(); - mEditor.onKeyDown(keyCode, event); - return true; - } - } catch (NullPointerException ex) { - - } - } - - - return false; - } - - @Override - public void onBackPressed() { - - try { - // if we should ignore the back button - if (PreferenceHelper.getIgnoreBackButton(this)) - return; - - if (mDrawerLayout.isDrawerOpen(Gravity.START) && fileOpened) { - mDrawerLayout.closeDrawer(Gravity.START); - } else if (mDrawerLayout.isDrawerOpen(Gravity.END) && fileOpened) { - mDrawerLayout.closeDrawer(Gravity.END); - } else if (fileOpened && mEditor.canSaveFile()) { - SaveFileDialog.newInstance(sFilePath, pageSystem.getAllText(mEditor - .getText().toString()), currentEncoding).show(getFragmentManager(), - "dialog"); - } else if (fileOpened) { - - // remove editor fragment - hideTextEditor(); - - // Set the default title - getSupportActionBar().setTitle(getString(R.string.nome_app_turbo_editor)); - - onEvent(new EventBusEvents.ClosedAFile()); - - mDrawerLayout.openDrawer(Gravity.START); - mDrawerLayout.closeDrawer(Gravity.END); - } else { - displayInterstitial(); - super.onBackPressed(); - } - } catch (Exception e) { - // maybe something is null, who knows - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK) { - String path = ""; - if (requestCode == SELECT_FILE_CODE) { - path = data.getStringExtra("path"); - if(TextUtils.isEmpty(path)) - path = AccessStorageApi.getPath(getBaseContext(), data.getData()); - } - - if (requestCode == KITKAT_OPEN_REQUEST_CODE) { - path = AccessStorageApi.getPath(getBaseContext(), data.getData()); - } - - if (!TextUtils.isEmpty(path)) { - File file = new File(path); - if (file.isFile() && file.exists()) { - onEvent(new EventBusEvents.NewFileToOpen(new File - (path))); - } - } - - } - } - - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - // Path of the file selected - String filePath = files.get(position).getAbsolutePath(); - // Send the event that a file was selected - onEvent(new EventBusEvents.NewFileToOpen(new File(filePath))); - } - - //endregion - - //region MENU - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - if (fileOpened && searchingText) - getMenuInflater().inflate(R.menu.fragment_editor_search, menu); - else if (fileOpened) - getMenuInflater().inflate(R.menu.fragment_editor, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - - if (fileOpened && searchingText) { - MenuItem imReplace = menu.findItem(R.id.im_replace); - MenuItem imPrev = menu.findItem(R.id.im_previous_item); - MenuItem imNext = menu.findItem(R.id.im_next_item); - - if (imReplace != null) - imReplace.setVisible(searchResult.canReplaceSomething()); - - if (imPrev != null) - imPrev.setVisible(searchResult.hasPrevious()); - - if (imNext != null) - imNext.setVisible(searchResult.hasNext()); - - - } else if (fileOpened) { - MenuItem imSave = menu.findItem(R.id.im_save); - MenuItem imUndo = menu.findItem(R.id.im_undo); - MenuItem imRedo = menu.findItem(R.id.im_redo); - if (mEditor != null) { - if (imSave != null) - imSave.setVisible(mEditor.canSaveFile()); - if (imUndo != null) - imUndo.setVisible(mEditor.getCanUndo()); - if (imRedo != null) - imRedo.setVisible(mEditor.getCanRedo()); - } else { - imSave.setVisible(false); - imUndo.setVisible(false); - imRedo.setVisible(false); - } - - MenuItem item = menu.findItem(R.id.im_share); - ShareActionProvider shareAction = (ShareActionProvider) MenuItemCompat - .getActionProvider(item); - File f = new File(sFilePath); - Intent shareIntent = new Intent(); - shareIntent.setAction(Intent.ACTION_SEND); - shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f)); - shareIntent.setType("text/plain"); - shareAction.setShareIntent(shareIntent); - } - - MenuItem imDonate = menu.findItem(R.id.im_donate); - if (imDonate != null) - if (ProCheckUtils.isPro(this, false)) - imDonate.setVisible(false); - - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int i = item.getItemId(); - if (mDrawerToggle.onOptionsItemSelected(item)) { - Toast.makeText(getBaseContext(), "drawer click", Toast.LENGTH_SHORT).show(); - mDrawerLayout.closeDrawer(Gravity.END); - return true; - } else if (i == R.id.im_save) { - saveTheFile(); - - } else if (i == R.id.im_undo) { - mEditor.onTextContextMenuItem(ID_UNDO); - - } else if (i == R.id.im_redo) { - mEditor.onTextContextMenuItem(ID_REDO); - - } else if (i == R.id.im_search) { - FindTextDialog.newInstance(mEditor.getText().toString()).show(getFragmentManager() - .beginTransaction(), "dialog"); - } else if (i == R.id.im_cancel) { - searchingText = false; - invalidateOptionsMenu(); - - } else if (i == R.id.im_replace) { - replaceText(); - - } else if (i == R.id.im_next_item) { - nextResult(); - - } else if (i == R.id.im_previous_item) { - previousResult(); - - } else if (i == R.id.im_goto_line) { - int min = mEditor.getLineUtils().firstReadLine(); - int max = mEditor.getLineUtils().lastReadLine(); - NumberPickerDialog.newInstance - (NumberPickerDialog.Actions.GoToLine, min, min, max).show(getFragmentManager().beginTransaction(), "dialog"); - } else if (i == R.id.im_view_it_on_browser) { - Intent browserIntent; - try { - browserIntent = new Intent(Intent.ACTION_VIEW); - browserIntent.setDataAndType(Uri.fromFile(new File(sFilePath)), "text/*"); - startActivity(browserIntent); - } catch (ActivityNotFoundException ex2) { - // - } - - } else if (i == R.id.im_info) { - FileInfoDialog.newInstance(sFilePath).show(getFragmentManager().beginTransaction(), "dialog"); - } - - else if (i == R.id.im_donate) { - DialogHelper.showDonateDialog(this); - } - return super.onOptionsItemSelected(item); - } - //endregion - - // region OTHER THINGS - void replaceText() { - int start = searchResult.foundIndex.get(searchResult.index); - int end = start + searchResult.textLength; - mEditor.setText(mEditor.getText().replace(start, end, searchResult.textToReplace)); - searchResult.doneReplace(); - - invalidateOptionsMenu(); - - if (searchResult.hasNext()) - nextResult(); - else if (searchResult.hasPrevious()) - previousResult(); - } - - void nextResult() { - if (searchResult.index == mEditor.getLineCount() - 1) // last result of page - { - return; - } - - - if (searchResult.index < searchResult.numberOfResults() - 1) { // equal zero is not good - searchResult.index++; - final int line = mEditor.getLineUtils().getLineFromIndex(searchResult.foundIndex.get - (searchResult.index), mEditor.getLineCount(), mEditor.getLayout()); - - - verticalScroll.post(new Runnable() { - @Override - public void run() { - int y = mEditor.getLayout().getLineTop(line); - if (y > 100) - y -= 100; - else - y = 0; - - verticalScroll.scrollTo(0, y); - } - }); - - mEditor.setFocusable(true); - mEditor.requestFocus(); - mEditor.setSelection(searchResult.foundIndex.get(searchResult.index), - searchResult.foundIndex.get(searchResult.index) + searchResult.textLength); - } - - invalidateOptionsMenu(); - } - - void previousResult() { - if (searchResult.index == 0) - return; - if (searchResult.index > 0) { - searchResult.index--; - final int line = LineUtils.getLineFromIndex(searchResult.foundIndex.get - (searchResult.index), mEditor.getLineCount(), mEditor.getLayout()); - verticalScroll.post(new Runnable() { - @Override - public void run() { - int y = mEditor.getLayout().getLineTop(line); - if (y > 100) - y -= 100; - else - y = 0; - verticalScroll.scrollTo(0, y); - } - }); - - mEditor.setFocusable(true); - mEditor.requestFocus(); - mEditor.setSelection(searchResult.foundIndex.get(searchResult.index), - searchResult.foundIndex.get(searchResult.index) + searchResult.textLength); - } - - invalidateOptionsMenu(); - } - - public abstract void displayInterstitial(); - - private void saveTheFile() { - File file = new File(sFilePath); - if (!file.getName().isEmpty()) - new SaveFileTask(this, sFilePath, pageSystem.getAllText(mEditor.getText() - .toString()), currentEncoding).execute(); - else { - NewFileDetailsDialog.newInstance - (pageSystem.getAllText(mEditor.getText().toString()), currentEncoding).show(getFragmentManager().beginTransaction(), "dialog"); - } - } - - /** - * Setup the navigation drawer - */ - private void setupNavigationDrawer() { - mDrawerLayout = (CustomDrawerLayout) findViewById(R.id.drawer_layout); - /* Action Bar - final ActionBar ab = toolbar; - ab.setDisplayHomeAsUpEnabled(true); - ab.setHomeButtonEnabled(true);*/ - /* Navigation drawer */ - mDrawerToggle = - new ActionBarDrawerToggle( - this, - mDrawerLayout, - toolbar, - R.string.nome_app_turbo_editor, - R.string.nome_app_turbo_editor) { - - @Override - public void onDrawerOpened(View drawerView) { - supportInvalidateOptionsMenu(); - try { - closeKeyBoard(); - } catch (NullPointerException e) { - e.printStackTrace(); - } - } - - @Override - public void onDrawerClosed(View view) { - supportInvalidateOptionsMenu(); - } - }; - /* link the mDrawerToggle to the Drawer Layout */ - mDrawerLayout.setDrawerListener(mDrawerToggle); -//mDrawerLayout.setFocusableInTouchMode(false); - - ListView listView = (ListView) findViewById(android.R.id.list); - listView.setEmptyView(findViewById(android.R.id.empty)); - files = new LinkedList<>(); - arrayAdapter = new AdapterDrawer(this, files, this); - listView.setAdapter(arrayAdapter); - listView.setOnItemClickListener(this); - } - - private void setupTextEditor() { - - verticalScroll = (GoodScrollView) findViewById(R.id.vertical_scroll); - horizontalScroll = (HorizontalScrollView) findViewById(R.id.horizontal_scroll); - mEditor = (Editor) findViewById(R.id.editor); - - //mEditor.setLayerType(View.LAYER_TYPE_NONE, null); - - if (PreferenceHelper.getWrapContent(this)) { - horizontalScroll.removeView(mEditor); - verticalScroll.removeView(horizontalScroll); - verticalScroll.addView(mEditor); - } - - if (PreferenceHelper.getReadOnly(this)) { - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); - } else { - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); - } - - verticalScroll.setScrollInterface(this); - - pageSystem = new PageSystem(this, this, "", null); - - pageSystemButtons = new PageSystemButtons(this, this, - (FloatingActionButton) findViewById(R.id.fabPrev), - (FloatingActionButton) findViewById(R.id.fabNext)); - } - - private void showTextEditor() { - - fileOpened = true; - - findViewById(R.id.text_editor).setVisibility(View.VISIBLE); - findViewById(R.id.no_file_opened_messagge).setVisibility(View.GONE); - - mEditor.resetVariables(); - searchResult = null; - searchingText = false; - - invalidateOptionsMenu(); - - mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText(), false); - mEditor.enableTextChangedListener(); - } - - private void hideTextEditor() { - - fileOpened = false; - - try { - findViewById(R.id.text_editor).setVisibility(View.GONE); - findViewById(R.id.no_file_opened_messagge).setVisibility(View.VISIBLE); - - mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor("", false); - mEditor.enableTextChangedListener(); - } catch (Exception e) { - // lol - } - } - - /** - * Parses the intent - */ - private void parseIntent(Intent intent) { - final String action = intent.getAction(); - final String type = intent.getType(); - - if (Intent.ACTION_VIEW.equals(action) - || Intent.ACTION_EDIT.equals(action) - || Intent.ACTION_PICK.equals(action) - && type != null) { - // Post event - onEvent(new EventBusEvents.NewFileToOpen(new File(intent - .getData().getPath()))); - } else if (Intent.ACTION_SEND.equals(action) && type != null) { - if ("text/plain".equals(type)) { - onEvent(new EventBusEvents.NewFileToOpen(intent.getStringExtra(Intent.EXTRA_TEXT))); - } - } - } - - /** - * Show a dialog with the changelog - */ - private void showChangeLog() { - final String currentVersion = AppInfoHelper.getCurrentVersion(this); - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - final String lastVersion = preferences.getString("last_version", currentVersion); - preferences.edit().putString("last_version", currentVersion).apply(); - if (!lastVersion.equals(currentVersion)) { - ChangelogDialog.showChangeLogDialog(getFragmentManager()); - } - } - - // closes the soft keyboard - private void closeKeyBoard() throws NullPointerException { - // Central system API to the overall input method framework (IMF) architecture - InputMethodManager inputManager = - (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - - // Base interface for a remotable object - IBinder windowToken = getCurrentFocus().getWindowToken(); - - // Hide type - int hideType = InputMethodManager.HIDE_NOT_ALWAYS; - - // Hide the KeyBoard - inputManager.hideSoftInputFromWindow(windowToken, hideType); - } - - void updateTextSyntax() { - if (!PreferenceHelper.getSyntaxHighlight(this) || mEditor.hasSelection() || - updateHandler == null || colorRunnable_duringEditing == null) - return; - - updateHandler.removeCallbacks(colorRunnable_duringEditing); - updateHandler.removeCallbacks(colorRunnable_duringScroll); - updateHandler.postDelayed(colorRunnable_duringEditing, SYNTAX_DELAY_MILLIS_LONG); - } - - private void refreshList(){ - refreshList(null, false, false); - } - - private void refreshList(@Nullable String path, boolean add, boolean delete) { - int max_recent_files = 15; - if(add) - max_recent_files--; - - // File paths saved in preferences - String[] savedPaths = PreferenceHelper.getSavedPaths(this); - int first_index_of_array = savedPaths.length > max_recent_files ? savedPaths.length - max_recent_files : 0; - savedPaths = ArrayUtils.subarray(savedPaths, first_index_of_array, savedPaths.length); - // File names for the list - files.clear(); - // StringBuilder that will contain the file paths - StringBuilder sb = new StringBuilder(); - // for cycle to convert paths to names - - for(int i = 0; i < savedPaths.length; i++){ - String savedPath = savedPaths[i]; - File file = new File(savedPath); - // Check that the file exist - if (file.exists()) { - if(path != null && path.equals(savedPath) && delete) - continue; - else { - files.addFirst(file); - sb.append(savedPath).append(","); - } - } - } - if(path != null && !path.isEmpty() && add && !ArrayUtils.contains(savedPaths, path)) { - sb.append(path).append(","); - files.addFirst(new File(path)); - } - // save list without empty or non existed files - PreferenceHelper.setSavedPaths(this, sb); - // Set adapter - arrayAdapter.notifyDataSetChanged(); - } - //endregion - - //region EVENTBUS - void onEvent(final EventBusEvents.NewFileToOpen event) { - - if (fileOpened && mEditor.canSaveFile()) { - SaveFileDialog.newInstance(sFilePath, pageSystem.getAllText(mEditor - .getText().toString()), currentEncoding, true, event.getFile().getAbsolutePath()).show(getFragmentManager(), - "dialog"); - return; - } - - new AsyncTask() { - - File file; - String message = ""; - String fileText; - String encoding; - ProgressDialog progressDialog; - - @Override - protected void onPreExecute() { - super.onPreExecute(); - // Close the drawer - mDrawerLayout.closeDrawer(Gravity.START); - progressDialog = new ProgressDialog(MainActivity.this); - progressDialog.setMessage(getString(R.string.please_wait)); - progressDialog.show(); - - } - - @Override - protected Void doInBackground(Void... params) { - file = event.getFile(); - try { - if (!file.exists() || !file.isFile()) { - fileText = event.getFileText(); - sFilePath = file.getAbsolutePath(); - fileExtension = "txt"; - return null; - } - - file = file.getCanonicalFile(); - sFilePath = file.getAbsolutePath(); - fileExtension = FilenameUtils.getExtension(sFilePath).toLowerCase(); - - boolean isRoot; - - if (!file.canRead()) { - Shell shell; - shell = Shell.startRootShell(); - Toolbox tb = new Toolbox(shell); - isRoot = tb.isRootAccessGiven(); - - if (isRoot) { - File tempFile = new File(getFilesDir(), "temp.root.file"); - if (!tempFile.exists()) - tempFile.createNewFile(); - tb.copyFile(event.getFile().getAbsolutePath(), - tempFile.getAbsolutePath(), false, false); - file = new File(tempFile.getAbsolutePath()); - } - } - - boolean autoencoding = PreferenceHelper.getAutoEncoding(MainActivity.this); - if (autoencoding) { - - encoding = FileUtils.getDetectedEncoding(file); - if (encoding.isEmpty()) { - encoding = PreferenceHelper.getEncoding(MainActivity.this); - } - } else { - encoding = PreferenceHelper.getEncoding(MainActivity.this); - } - - fileText = org.apache.commons.io.FileUtils.readFileToString(file, encoding); - } catch (Exception e) { - message = e.getMessage(); - fileText = ""; - } - - while (mDrawerLayout.isDrawerOpen(Gravity.START)) { - try { - Thread.sleep(50); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - return null; - } - - @Override - protected void onPostExecute(Void result) { - super.onPostExecute(result); - progressDialog.hide(); - - if (!message.isEmpty()) { - Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show(); - onEvent(new EventBusEvents.CannotOpenAFile()); - } else { - - pageSystem = new PageSystem(MainActivity.this, MainActivity.this, fileText, new File(sFilePath)); - currentEncoding = encoding; - - onEvent(new EventBusEvents.AFileIsSelected(sFilePath)); - - showTextEditor(); - - String name = FilenameUtils.getName(sFilePath); - if (name.isEmpty()) - getSupportActionBar().setTitle(R.string.new_file); - else - getSupportActionBar().setTitle(name); - - if(!name.isEmpty()) { - refreshList(sFilePath, true, false); - } - } - - } - }.execute(); - } - - public void onEvent(EventBusEvents.SavedAFile event) { - - sFilePath = event.getPath(); - fileExtension = FilenameUtils.getExtension(sFilePath).toLowerCase(); - - mEditor.clearHistory(); - mEditor.fileSaved(); - invalidateOptionsMenu(); - - try { - closeKeyBoard(); - } catch (NullPointerException e) { - e.printStackTrace(); - } - - refreshList(event.getPath(), true, false); - arrayAdapter.selectView(event.getPath()); - - displayInterstitial(); - } - - /** - * When a file can't be opened - * Invoked by the EditorFragment - * - * @param event The event called - */ - void onEvent(EventBusEvents.CannotOpenAFile event) { - // - mDrawerLayout.openDrawer(Gravity.LEFT); - // - getSupportActionBar().setTitle(getString(R.string.nome_app_turbo_editor)); - // - supportInvalidateOptionsMenu(); - // Replace fragment - hideTextEditor(); - } - - public void onEvent(EventBusEvents.APreferenceValueWasChanged event) { - - if (event.hasType(EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE)) { - ThemeUtils.setWindowsBackground(this); - } - - if (event.hasType(WRAP_CONTENT)) { - if (PreferenceHelper.getWrapContent(this)) { - horizontalScroll.removeView(mEditor); - verticalScroll.removeView(horizontalScroll); - verticalScroll.addView(mEditor); - } else { - verticalScroll.removeView(mEditor); - verticalScroll.addView(horizontalScroll); - horizontalScroll.addView(mEditor); - } - } else if (event.hasType(LINE_NUMERS)) { - mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor(null, true); - mEditor.enableTextChangedListener(); - if (PreferenceHelper.getLineNumbers(this)) { - mEditor.setPadding(EditTextPadding.getPaddingWithLineNumbers(this, - PreferenceHelper.getFontSize(this)), - EditTextPadding.getPaddingTop(this), 0, 0); - } else { - mEditor.setPadding(EditTextPadding.getPaddingWithoutLineNumbers(this) - , EditTextPadding.getPaddingTop(this), 0, 0); - } - } else if (event.hasType(SYNTAX)) { - mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor(null, true); - mEditor.enableTextChangedListener(); - } else if (event.hasType(MONOSPACE)) { - if (PreferenceHelper.getUseMonospace(this)) - mEditor.setTypeface(Typeface.MONOSPACE); - else - mEditor.setTypeface(Typeface.DEFAULT); - } else if (event.hasType(THEME_CHANGE)) { - if (PreferenceHelper.getLightTheme(this)) { - mEditor.setTextColor(getResources().getColor(R.color.textColorInverted)); - } else { - mEditor.setTextColor(getResources().getColor(R.color.textColor)); - } - } else if (event.hasType(TEXT_SUGGESTIONS) || event.hasType(READ_ONLY)) { - if (PreferenceHelper.getReadOnly(this)) { - getWindow().setSoftInputMode(WindowManager.LayoutParams - .SOFT_INPUT_STATE_ALWAYS_HIDDEN); - mEditor.setReadOnly(true); - } else { - getWindow().setSoftInputMode(WindowManager.LayoutParams - .SOFT_INPUT_STATE_UNSPECIFIED); - mEditor.setReadOnly(false); - if (PreferenceHelper.getSuggestionActive(this)) { - mEditor.setInputType(InputType.TYPE_CLASS_TEXT | InputType - .TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE); - } else { - mEditor.setInputType(InputType.TYPE_CLASS_TEXT | InputType - .TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS - | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType - .TYPE_TEXT_FLAG_IME_MULTI_LINE); - } - } - // sometimes it becomes monospace after setting the input type - if (PreferenceHelper.getUseMonospace(this)) - mEditor.setTypeface(Typeface.MONOSPACE); - else - mEditor.setTypeface(Typeface.DEFAULT); - } else if (event.hasType(FONT_SIZE)) { - if (PreferenceHelper.getLineNumbers(this)) { - mEditor.setPadding(EditTextPadding.getPaddingWithLineNumbers(this, - PreferenceHelper.getFontSize(this)), - EditTextPadding.getPaddingTop(this), 0, 0); - } else { - mEditor.setPadding(EditTextPadding.getPaddingWithoutLineNumbers(this) - , EditTextPadding.getPaddingTop(this), 0, 0); - } - mEditor.setTextSize(PreferenceHelper.getFontSize(this)); - } else if (event.hasType(ENCODING)) { - String oldEncoding, newEncoding; - oldEncoding = currentEncoding; - newEncoding = PreferenceHelper.getEncoding(this); - try { - final byte[] oldText = mEditor.getText().toString().getBytes(oldEncoding); - mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor(new String(oldText, newEncoding), true); - mEditor.enableTextChangedListener(); - currentEncoding = newEncoding; - } catch (UnsupportedEncodingException ignored) { - try { - final byte[] oldText = mEditor.getText().toString().getBytes(oldEncoding); - mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor(new String(oldText, "UTF-8"), true); - mEditor.enableTextChangedListener(); - } catch (UnsupportedEncodingException ignored2) { - } - } - } - } - - void onEvent(EventBusEvents.AFileIsSelected event) { - arrayAdapter.selectView(event.getPath()); - } - - void onEvent(EventBusEvents.ClosedAFile event) { - arrayAdapter.selectView(""); - } - //endregion - - //region Calls from the layout - public void OpenFile(View view) { - Intent subActivity = new Intent(MainActivity.this, SelectFileActivity.class); - subActivity.putExtra("action", SelectFileActivity.Actions.SelectFile); - AnimationUtils.startActivityWithScale(this, subActivity, true, SELECT_FILE_CODE, view); - } - - public void CreateFile(View view) { - onEvent(new EventBusEvents.NewFileToOpen("")); // do not send the event to others - } - - public void OpenInfo(View view) { - DialogHelper.showAboutDialog(this); - } - - public void OpenSettings(View view) { - mDrawerLayout.closeDrawer(Gravity.START); - mDrawerLayout.openDrawer(Gravity.END); - } - //endregion - - //region Ovverideses - @Override - public void nextPageClicked() { - pageSystem.savePage(mEditor.getText().toString()); - pageSystem.nextPage(); - mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText(), false); - mEditor.enableTextChangedListener(); - - verticalScroll.postDelayed(new Runnable() { - @Override - public void run() { - verticalScroll.smoothScrollTo(0, 0); - } - }, 200); - - if (!PreferenceHelper.getPageSystemButtonsPopupShown(this)) { - PreferenceHelper.setPageSystemButtonsPopupShown(this, true); - Toast.makeText(this, getString(R.string.long_click_for_more_options), - Toast.LENGTH_LONG).show(); - } - } - - @Override - public void prevPageClicked() { - pageSystem.savePage(mEditor.getText().toString()); - pageSystem.prevPage(); - mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText(), false); - mEditor.enableTextChangedListener(); - - verticalScroll.postDelayed(new Runnable() { - @Override - public void run() { - verticalScroll.smoothScrollTo(0, 0); - } - }, 200); - - if (!PreferenceHelper.getPageSystemButtonsPopupShown(this)) { - PreferenceHelper.setPageSystemButtonsPopupShown(this, true); - Toast.makeText(this, getString(R.string.long_click_for_more_options), - Toast.LENGTH_LONG).show(); - } - } - - @Override - public void pageSystemButtonLongClicked() { - int maxPages = pageSystem.getMaxPage(); - int currentPage = pageSystem.getCurrentPage(); - NumberPickerDialog.newInstance - (NumberPickerDialog.Actions.SelectPage, 0, currentPage, maxPages).show(getFragmentManager().beginTransaction(), "dialog"); - } - - @Override - public boolean canReadNextPage() { - return pageSystem.canReadNextPage(); - } - - @Override - public boolean canReadPrevPage() { - return pageSystem.canReadPrevPage(); - } - - @Override - public void onSearchDone(SearchResult searchResult) { - MainActivity.searchResult = searchResult; - searchingText = true; - invalidateOptionsMenu(); - - final int line = LineUtils.getLineFromIndex(searchResult.foundIndex.getFirst - (), mEditor.getLineCount(), mEditor.getLayout()); - verticalScroll.post(new Runnable() { - @Override - public void run() { - int y = mEditor.getLayout().getLineTop(line); - if (y > 100) - y -= 100; - else - y = 0; - - verticalScroll.scrollTo(0, y); - } - }); - - mEditor.setFocusable(true); - mEditor.requestFocus(); - mEditor.setSelection(searchResult.foundIndex.getFirst(), searchResult.foundIndex.getFirst - () + searchResult.textLength); - - } - - @Override - public void onPageChanged(int page) { - pageSystemButtons.updateVisibility(false); - searchingText = false; - mEditor.clearHistory(); - invalidateOptionsMenu(); - } - - @Override - public void onScrollChanged(int l, int t, int oldl, int oldt) { - pageSystemButtons.updateVisibility(Math.abs(t) > 10); - - if (!PreferenceHelper.getSyntaxHighlight(this) || (mEditor.hasSelection() && - !searchingText) || updateHandler == null || colorRunnable_duringScroll == null) - return; - - updateHandler.removeCallbacks(colorRunnable_duringEditing); - updateHandler.removeCallbacks(colorRunnable_duringScroll); - updateHandler.postDelayed(colorRunnable_duringScroll, SYNTAX_DELAY_MILLIS_SHORT); - } - - @Override - public void onNumberPickerDialogDismissed(NumberPickerDialog.Actions action, int value) { - if (action == NumberPickerDialog.Actions.SelectPage) { - pageSystem.savePage(mEditor.getText().toString()); - pageSystem.goToPage(value); - mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText(), true); - mEditor.enableTextChangedListener(); - - verticalScroll.postDelayed(new Runnable() { - @Override - public void run() { - verticalScroll.smoothScrollTo(0, 0); - } - }, 200); - - } else if (action == NumberPickerDialog.Actions.GoToLine) { - - int fakeLine = mEditor.getLineUtils().fakeLineFromRealLine(value); - final int y = mEditor.getLineUtils().getYAtLine(verticalScroll, - mEditor.getLineCount(), fakeLine); - - verticalScroll.postDelayed(new Runnable() { - @Override - public void run() { - verticalScroll.smoothScrollTo(0, y); - } - }, 200); - } - - } - - @Override - public void userDoesntWantToSave(boolean openNewFile, String pathOfNewFile) { - Editor.canSaveFile = false; - if(openNewFile) - onEvent(new EventBusEvents.NewFileToOpen(new File(pathOfNewFile))); - else - onEvent(new EventBusEvents.CannotOpenAFile()); - } - - @Override - public void CancelItem(int position, boolean andCloseOpenedFile) { - refreshList(files.get(position).getAbsolutePath(), false, true); - if (andCloseOpenedFile) - onEvent(new EventBusEvents.CannotOpenAFile()); - } - //endregion - - public static class Editor extends EditText { - - //region VARIABLES - private static final TextPaint mPaintNumbers = new TextPaint(); - /** - * The edit history. - */ - private final EditHistory mEditHistory; - /** - * The change listener. - */ - private final EditTextChangeListener - mChangeListener; - /** - * Disconnect this undo/redo from the text - * view. - */ - private static boolean enabledChangeListener; - private static int paddingTop; - private static int numbersWidth; - private static int lineHeight; - - private static int lineCount, realLine, startingLine; - private static LineUtils lineUtils; - /** - * Is undo/redo being performed? This member - * signals if an undo/redo operation is - * currently being performed. Changes in the - * text during undo/redo are not recorded - * because it would mess up the undo history. - */ - private static boolean mIsUndoOrRedo; - private static Matcher m; - private static boolean mShowUndo, mShowRedo; - private static boolean canSaveFile; - private static KeyListener keyListener; - private static int firstVisibleIndex, firstColoredIndex; - private static int deviceHeight; - private static int editorHeight; - private static boolean[] hasNewLineArray; - private static int[] realLines; - private static boolean wrapContent; - private static int lastLine; - private static int firstLine; - private static CharSequence textToHighlight; - private static int lastVisibleIndex; - private static int i; - //endregion - - //region CONSTRUCTOR - public Editor(final Context context, AttributeSet attrs) { - super(context, attrs); - - //setLayerType(View.LAYER_TYPE_NONE, null); - - mEditHistory = new EditHistory(); - mChangeListener = new EditTextChangeListener(); - lineUtils = new LineUtils(); - - deviceHeight = getResources().getDisplayMetrics().heightPixels; - - paddingTop = EditTextPadding.getPaddingTop(getContext()); - - mPaintNumbers.setAntiAlias(true); - mPaintNumbers.setDither(false); - mPaintNumbers.setTextAlign(Paint.Align.RIGHT); - mPaintNumbers.setColor(getResources().getColor(R.color.file_text)); - - if (PreferenceHelper.getLightTheme(getContext())) { - setTextColor(getResources().getColor(R.color.textColorInverted)); - } else { - setTextColor(getResources().getColor(R.color.textColor)); - } - if (PreferenceHelper.getLineNumbers(getContext())) { - setPadding(EditTextPadding.getPaddingWithLineNumbers(getContext(), - PreferenceHelper.getFontSize(getContext())), - EditTextPadding.getPaddingTop(getContext()), 0, 0); - } else { - setPadding(EditTextPadding.getPaddingWithoutLineNumbers(getContext()), - EditTextPadding.getPaddingTop(getContext()), 0, 0); - } - - if (PreferenceHelper.getReadOnly(getContext())) { - setReadOnly(true); - } else { - setReadOnly(false); - if (PreferenceHelper.getSuggestionActive(getContext())) { - setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE - | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE); - } else { - setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE - | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType - .TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType - .TYPE_TEXT_FLAG_IME_MULTI_LINE); - } - } - - if (PreferenceHelper.getUseMonospace(getContext())) { - setTypeface(Typeface.MONOSPACE); - } else { - setTypeface(Typeface.DEFAULT); - } - setTextSize(PreferenceHelper.getFontSize(getContext())); - - setFocusable(true); - setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (!PreferenceHelper.getReadOnly(getContext())) { - verticalScroll.tempDisableListener(1000); - ((InputMethodManager) getContext().getSystemService(Context - .INPUT_METHOD_SERVICE)) - .showSoftInput(Editor.this, InputMethodManager.SHOW_IMPLICIT); - } - - } - }); - setOnFocusChangeListener(new View.OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (hasFocus && !PreferenceHelper.getReadOnly(getContext())) { - verticalScroll.tempDisableListener(1000); - ((InputMethodManager) getContext().getSystemService(Context - .INPUT_METHOD_SERVICE)) - .showSoftInput(Editor.this, InputMethodManager.SHOW_IMPLICIT); - } - } - }); - - setMaxHistorySize(30); - - resetVariables(); - } - - public void setReadOnly(boolean value) { - if (value) { - keyListener = getKeyListener(); - setKeyListener(null); - } else { - if (keyListener != null) - setKeyListener(keyListener); - } - } - - //region OVERRIDES - @Override - public void setTextSize(float size) { - super.setTextSize(size); - final float scale = getContext().getResources().getDisplayMetrics().density; - mPaintNumbers.setTextSize((int) (size * scale * 0.65f)); - numbersWidth = (int) (EditTextPadding.getPaddingWithLineNumbers(getContext(), - PreferenceHelper.getFontSize(getContext())) * 0.8); - lineHeight = getLineHeight(); - } - - - @Override - public void onDraw(@NonNull final Canvas canvas) { - - if (lineCount != getLineCount() || startingLine != pageSystem.getStartingLine()) { - startingLine = pageSystem.getStartingLine(); - lineCount = getLineCount(); - lineUtils.updateHasNewLineArray(pageSystem - .getStartingLine(), lineCount, getLayout(), getText().toString()); - - hasNewLineArray = lineUtils.getToCountLinesArray(); - realLines = lineUtils.getRealLines(); - - } - - editorHeight = getHeight(); - firstLine = lineUtils.getFirstVisibleLine(verticalScroll, editorHeight, lineCount); - lastLine = lineUtils.getLastVisibleLine(verticalScroll, editorHeight, lineCount, deviceHeight); - - if (PreferenceHelper.getLineNumbers(getContext())) { - wrapContent = PreferenceHelper.getWrapContent(getContext()); - i = firstLine; - - while (i < lastLine) { - // if last line we count it anyway - if (!wrapContent - || hasNewLineArray[i] - || i == lastLine - 1) { - if (i == lastLine - 1) - realLine = realLines[i] + 1; - else - realLine = realLines[i]; - - canvas.drawText(String.valueOf(realLine), - numbersWidth, // they are all center aligned - paddingTop + lineHeight * (i + 1), - mPaintNumbers); - } - i++; - } - } - - super.onDraw(canvas); - } - - - //endregion - - //region Other - - @Override - public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { - - if (event.isCtrlPressed()) { - switch (keyCode) { - case KeyEvent.KEYCODE_A: - return onTextContextMenuItem(ID_SELECT_ALL); - case KeyEvent.KEYCODE_X: - return onTextContextMenuItem(ID_CUT); - case KeyEvent.KEYCODE_C: - return onTextContextMenuItem(ID_COPY); - case KeyEvent.KEYCODE_V: - return onTextContextMenuItem(ID_PASTE); - case KeyEvent.KEYCODE_Z: - if (getCanUndo()) { - return onTextContextMenuItem(ID_UNDO); - } - case KeyEvent.KEYCODE_Y: - if (getCanRedo()) { - return onTextContextMenuItem(ID_REDO); - } - case KeyEvent.KEYCODE_S: - ((MainActivity) getContext()).saveTheFile(); - return true; - default: - return super.onKeyDown(keyCode, event); - } - } else { - switch (keyCode) { - case KeyEvent.KEYCODE_TAB: - String textToInsert = " "; - int start, end; - start = Math.max(getSelectionStart(), 0); - end = Math.max(getSelectionEnd(), 0); - getText().replace(Math.min(start, end), Math.max(start, end), - textToInsert, 0, textToInsert.length()); - return true; - default: - return super.onKeyDown(keyCode, event); - } - } - } - - @Override - public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) { - if (event.isCtrlPressed()) { - switch (keyCode) { - case KeyEvent.KEYCODE_A: - case KeyEvent.KEYCODE_X: - case KeyEvent.KEYCODE_C: - case KeyEvent.KEYCODE_V: - case KeyEvent.KEYCODE_Z: - case KeyEvent.KEYCODE_Y: - case KeyEvent.KEYCODE_S: - return true; - default: - return false; - } - } else { - switch (keyCode) { - case KeyEvent.KEYCODE_TAB: - return true; - default: - return false; - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean onTextContextMenuItem( - final int id) { - if (id == ID_UNDO) { - undo(); - return true; - } else if (id == ID_REDO) { - redo(); - return true; - } else { - return super.onTextContextMenuItem(id); - } - } - - /** - * Can undo be performed? - */ - public boolean getCanUndo() { - return (mEditHistory.mmPosition > 0); - } - - /** - * Can redo be performed? - */ - public boolean getCanRedo() { - return (mEditHistory.mmPosition - < mEditHistory.mmHistory.size()); - } - - /** - * Perform undo. - */ - public void undo() { - EditItem edit = mEditHistory.getPrevious(); - if (edit == null) { - return; - } - - Editable text = getEditableText(); - int start = edit.mmStart; - int end = start + (edit.mmAfter != null - ? edit.mmAfter.length() : 0); - - mIsUndoOrRedo = true; - text.replace(start, end, edit.mmBefore); - mIsUndoOrRedo = false; - - // This will get rid of underlines inserted when editor tries to come - // up with a suggestion. - for (Object o : text.getSpans(0, - text.length(), UnderlineSpan.class)) { - text.removeSpan(o); - } - - Selection.setSelection(text, - edit.mmBefore == null ? start - : (start + edit.mmBefore.length())); - } - - /** - * Perform redo. - */ - public void redo() { - EditItem edit = mEditHistory.getNext(); - if (edit == null) { - return; - } - - Editable text = getEditableText(); - int start = edit.mmStart; - int end = start + (edit.mmBefore != null - ? edit.mmBefore.length() : 0); - - mIsUndoOrRedo = true; - text.replace(start, end, edit.mmAfter); - mIsUndoOrRedo = false; - - // This will get rid of underlines inserted when editor tries to come - // up with a suggestion. - for (Object o : text.getSpans(0, - text.length(), UnderlineSpan.class)) { - text.removeSpan(o); - } - - Selection.setSelection(text, - edit.mmAfter == null ? start - : (start + edit.mmAfter.length())); - } - - /** - * Set the maximum history size. If size is - * negative, then history size is only limited - * by the device memory. - */ - public void setMaxHistorySize( - int maxHistorySize) { - mEditHistory.setMaxHistorySize( - maxHistorySize); - } - - public void resetVariables() { - mEditHistory.clear(); - enabledChangeListener = false; - lineCount = 0; - realLine = 0; - startingLine = 0; - mIsUndoOrRedo = false; - mShowUndo = false; - mShowRedo = false; - canSaveFile = false; - firstVisibleIndex = 0; - firstColoredIndex = 0; - } - - public boolean canSaveFile() { - return canSaveFile; - } - - public void fileSaved() { - canSaveFile = false; - } - - public void replaceTextKeepCursor(String textToUpdate, boolean mantainCursorPos) { - - int cursorPos; - int cursorPosEnd; - if (textToUpdate != null) { - cursorPos = 0; - cursorPosEnd = 0; - } else { - cursorPos = getSelectionStart(); - cursorPosEnd = getSelectionEnd(); - } - disableTextChangedListener(); - - if (PreferenceHelper.getSyntaxHighlight(getContext())) - setText(highlight(textToUpdate == null ? getEditableText() : Editable.Factory - .getInstance().newEditable(textToUpdate), textToUpdate != null)); - else - setText(textToUpdate == null ? getText().toString() : textToUpdate); - - enableTextChangedListener(); - - if (mantainCursorPos) - firstVisibleIndex = cursorPos; - - if (firstVisibleIndex > -1) { - if (cursorPosEnd != cursorPos) - setSelection(cursorPos, cursorPosEnd); - else - setSelection(firstVisibleIndex); - } - } - //endregion - - //region UNDO REDO - - public void disableTextChangedListener() { - enabledChangeListener = false; - removeTextChangedListener(mChangeListener); - } - - public CharSequence highlight(Editable editable, boolean newText) { - editable.clearSpans(); - - if (editable.length() == 0) { - return editable; - } - - editorHeight = getHeight(); - - if (!newText && editorHeight > 0) { - firstLine = lineUtils.getFirstVisibleLine(verticalScroll, editorHeight, lineCount); - lastLine = lineUtils.getLastVisibleLine(verticalScroll, editorHeight, lineCount, deviceHeight); - firstVisibleIndex = getLayout().getLineStart(firstLine); - lastVisibleIndex = getLayout().getLineStart(lastLine); - } else { - firstVisibleIndex = 0; - lastVisibleIndex = CHARS_TO_COLOR; - } - - firstColoredIndex = firstVisibleIndex - (CHARS_TO_COLOR / 5); - - // normalize - if (firstColoredIndex < 0) - firstColoredIndex = 0; - if (lastVisibleIndex > editable.length()) - lastVisibleIndex = editable.length(); - if (firstColoredIndex > lastVisibleIndex) - firstColoredIndex = lastVisibleIndex; - - - textToHighlight = editable.subSequence(firstColoredIndex, lastVisibleIndex); - - if (fileExtension.contains("htm") - || fileExtension.contains("xml")) { - color(Patterns.HTML_OPEN_TAGS, editable, textToHighlight, firstColoredIndex); - color(Patterns.HTML_CLOSE_TAGS, editable, textToHighlight, firstColoredIndex); - color(Patterns.HTML_ATTRS, editable, textToHighlight, firstColoredIndex); - color(Patterns.GENERAL_STRINGS, editable, textToHighlight, firstColoredIndex); - color(Patterns.XML_COMMENTS, editable, textToHighlight, firstColoredIndex); - } else if (fileExtension.equals("css")) { - //color(CSS_STYLE_NAME, editable); - color(Patterns.CSS_ATTRS, editable, textToHighlight, firstColoredIndex); - color(Patterns.CSS_ATTR_VALUE, editable, textToHighlight, firstColoredIndex); - color(Patterns.SYMBOLS, editable, textToHighlight, firstColoredIndex); - color(Patterns.GENERAL_COMMENTS, editable, textToHighlight, firstColoredIndex); - } else if (Arrays.asList(MimeTypes.MIME_CODE).contains(fileExtension)) { - switch (fileExtension) { - case "lua": - color(Patterns.LUA_KEYWORDS, editable, textToHighlight, firstColoredIndex); - break; - case "py": - color(Patterns.PY_KEYWORDS, editable, textToHighlight, firstColoredIndex); - break; - default: - color(Patterns.GENERAL_KEYWORDS, editable, textToHighlight, firstColoredIndex); - break; - } - color(Patterns.NUMBERS_OR_SYMBOLS, editable, textToHighlight, firstColoredIndex); - color(Patterns.GENERAL_STRINGS, editable, textToHighlight, firstColoredIndex); - color(Patterns.GENERAL_COMMENTS, editable, textToHighlight, firstColoredIndex); - if (fileExtension.equals("php")) - color(Patterns.PHP_VARIABLES, editable, textToHighlight, firstColoredIndex); - } else if (Arrays.asList(MimeTypes.MIME_SQL).contains(fileExtension)) { - color(Patterns.SYMBOLS, editable, textToHighlight, firstColoredIndex); - color(Patterns.GENERAL_STRINGS, editable, textToHighlight, firstColoredIndex); - color(Patterns.SQL_KEYWORDS, editable, textToHighlight, firstColoredIndex); - } else { - if (!(Arrays.asList(MimeTypes.MIME_MARKDOWN).contains(fileExtension))) - color(Patterns.GENERAL_KEYWORDS, editable, textToHighlight, firstColoredIndex); - color(Patterns.NUMBERS_OR_SYMBOLS, editable, textToHighlight, firstColoredIndex); - color(Patterns.GENERAL_STRINGS, editable, textToHighlight, firstColoredIndex); - if (fileExtension.equals("prop") || fileExtension.contains("conf") || - (Arrays.asList(MimeTypes.MIME_MARKDOWN).contains(fileExtension))) - color(Patterns.GENERAL_COMMENTS_NO_SLASH, editable, textToHighlight, - firstColoredIndex); - else - color(Patterns.GENERAL_COMMENTS, editable, textToHighlight, firstColoredIndex); - - if ((Arrays.asList(MimeTypes.MIME_MARKDOWN).contains(fileExtension))) - color(Patterns.LINK, editable, textToHighlight, firstColoredIndex); - } - - return editable; - } - - public void enableTextChangedListener() { - if (!enabledChangeListener) { - addTextChangedListener(mChangeListener); - enabledChangeListener = true; - } - } - - public LineUtils getLineUtils() { - return lineUtils; - } - - private void color(Pattern pattern, - Editable allText, - CharSequence textToHighlight, - int start) { - int color = 0; - if (pattern.equals(Patterns.HTML_OPEN_TAGS) - || pattern.equals(Patterns.HTML_CLOSE_TAGS) - || pattern.equals(Patterns.GENERAL_KEYWORDS) - || pattern.equals(Patterns.SQL_KEYWORDS) - || pattern.equals(Patterns.PY_KEYWORDS) - || pattern.equals(Patterns.LUA_KEYWORDS) - - ) { - color = getResources().getColor(R.color.syntax_keyword); - } else if (pattern.equals(Patterns.HTML_ATTRS) - || pattern.equals(Patterns.CSS_ATTRS) - || pattern.equals(Patterns.LINK)) { - color = getResources().getColor(R.color.syntax_attr); - } else if (pattern.equals(Patterns.CSS_ATTR_VALUE)) { - color = getResources().getColor(R.color.syntax_attr_value); - } else if (pattern.equals(Patterns.XML_COMMENTS) - || pattern.equals(Patterns.GENERAL_COMMENTS) - || pattern.equals(Patterns.GENERAL_COMMENTS_NO_SLASH)) { - color = getResources().getColor(R.color.syntax_comment); - } else if (pattern.equals(Patterns.GENERAL_STRINGS)) { - color = getResources().getColor(R.color.syntax_string); - } else if (pattern.equals(Patterns.NUMBERS) || pattern.equals(Patterns.SYMBOLS) || pattern.equals(Patterns.NUMBERS_OR_SYMBOLS)) { - color = getResources().getColor(R.color.syntax_number); - } else if (pattern.equals(Patterns.PHP_VARIABLES)) { - color = getResources().getColor(R.color.syntax_variable); - } - - m = pattern.matcher(textToHighlight); - - while (m.find()) { - allText.setSpan( - new ForegroundColorSpan(color), - start + m.start(), - start + m.end(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - } - - /** - * Clear history. - */ - public void clearHistory() { - mEditHistory.clear(); - mShowUndo = getCanUndo(); - mShowRedo = getCanRedo(); - } - - /** - * Store preferences. - */ - public void storePersistentState( - SharedPreferences.Editor editor, - String prefix) { - // Store hash code of text in the editor so that we can check if the - // editor contents has changed. - editor.putString(prefix + ".hash", - String.valueOf( - getText().toString().hashCode())); - editor.putInt(prefix + ".maxSize", - mEditHistory.mmMaxHistorySize); - editor.putInt(prefix + ".position", - mEditHistory.mmPosition); - editor.putInt(prefix + ".size", - mEditHistory.mmHistory.size()); - - int i = 0; - for (EditItem ei : mEditHistory.mmHistory) { - String pre = prefix + "." + i; - - editor.putInt(pre + ".start", ei.mmStart); - editor.putString(pre + ".before", - ei.mmBefore.toString()); - editor.putString(pre + ".after", - ei.mmAfter.toString()); - - i++; - } - } - - /** - * Restore preferences. - * - * @param prefix The preference key prefix - * used when state was stored. - * @return did restore succeed? If this is - * false, the undo history will be empty. - */ - public boolean restorePersistentState( - SharedPreferences sp, String prefix) - throws IllegalStateException { - - boolean ok = - doRestorePersistentState(sp, prefix); - if (!ok) { - mEditHistory.clear(); - } - - return ok; - } - - private boolean doRestorePersistentState( - SharedPreferences sp, String prefix) { - - String hash = - sp.getString(prefix + ".hash", null); - if (hash == null) { - // No state to be restored. - return true; - } - - if (Integer.valueOf(hash) - != getText().toString().hashCode()) { - return false; - } - - mEditHistory.clear(); - mEditHistory.mmMaxHistorySize = - sp.getInt(prefix + ".maxSize", -1); - - int count = sp.getInt(prefix + ".size", -1); - if (count == -1) { - return false; - } - - for (int i = 0; i < count; i++) { - String pre = prefix + "." + i; - - int start = sp.getInt(pre + ".start", -1); - String before = - sp.getString(pre + ".before", null); - String after = - sp.getString(pre + ".after", null); - - if (start == -1 - || before == null - || after == null) { - return false; - } - mEditHistory.add( - new EditItem(start, before, after)); - } - - mEditHistory.mmPosition = - sp.getInt(prefix + ".position", -1); - return mEditHistory.mmPosition != -1; - - } - - /** - * Class that listens to changes in the text. - */ - private final class EditTextChangeListener - implements TextWatcher { - - /** - * The text that will be removed by the - * change event. - */ - private CharSequence mBeforeChange; - - /** - * The text that was inserted by the change - * event. - */ - private CharSequence mAfterChange; - - public void beforeTextChanged( - CharSequence s, int start, int count, - int after) { - if (mIsUndoOrRedo) { - return; - } - - mBeforeChange = - s.subSequence(start, start + count); - } - - public void onTextChanged(CharSequence s, - int start, int before, - int count) { - if (mIsUndoOrRedo) { - return; - } - - mAfterChange = - s.subSequence(start, start + count); - mEditHistory.add( - new EditItem(start, mBeforeChange, - mAfterChange)); - } - - public void afterTextChanged(Editable s) { - boolean showUndo = getCanUndo(); - boolean showRedo = getCanRedo(); - if (!canSaveFile) - canSaveFile = getCanUndo(); - if (showUndo != mShowUndo || showRedo != mShowRedo) { - mShowUndo = showUndo; - mShowRedo = showRedo; - ((MainActivity) getContext()).invalidateOptionsMenu(); - } - - ((MainActivity) getContext()).updateTextSyntax(); - } - } - - //endregion - - //region EDIT HISTORY - - /** - * Keeps track of all the edit history of a - * text. - */ - private final class EditHistory { - - /** - * The list of edits in chronological - * order. - */ - private final LinkedList - mmHistory = new LinkedList<>(); - /** - * The position from which an EditItem will - * be retrieved when getNext() is called. If - * getPrevious() has not been called, this - * has the same value as mmHistory.size(). - */ - private int mmPosition = 0; - /** - * Maximum undo history size. - */ - private int mmMaxHistorySize = -1; - - private int size() { - return mmHistory.size(); - } - - /** - * Clear history. - */ - private void clear() { - mmPosition = 0; - mmHistory.clear(); - } - - /** - * Adds a new edit operation to the history - * at the current position. If executed - * after a call to getPrevious() removes all - * the future history (elements with - * positions >= current history position). - */ - private void add(EditItem item) { - while (mmHistory.size() > mmPosition) { - mmHistory.removeLast(); - } - mmHistory.add(item); - mmPosition++; - - if (mmMaxHistorySize >= 0) { - trimHistory(); - } - } - - /** - * Trim history when it exceeds max history - * size. - */ - private void trimHistory() { - while (mmHistory.size() - > mmMaxHistorySize) { - mmHistory.removeFirst(); - mmPosition--; - } - - if (mmPosition < 0) { - mmPosition = 0; - } - } - - /** - * Set the maximum history size. If size is - * negative, then history size is only - * limited by the device memory. - */ - private void setMaxHistorySize( - int maxHistorySize) { - mmMaxHistorySize = maxHistorySize; - if (mmMaxHistorySize >= 0) { - trimHistory(); - } - } - - /** - * Traverses the history backward by one - * position, returns and item at that - * position. - */ - private EditItem getPrevious() { - if (mmPosition == 0) { - return null; - } - mmPosition--; - return mmHistory.get(mmPosition); - } - - /** - * Traverses the history forward by one - * position, returns and item at that - * position. - */ - private EditItem getNext() { - if (mmPosition >= mmHistory.size()) { - return null; - } - - EditItem item = mmHistory.get(mmPosition); - mmPosition++; - return item; - } - } - - /** - * Represents the changes performed by a - * single edit operation. - */ - private final class EditItem { - private final int mmStart; - private final CharSequence mmBefore; - private final CharSequence mmAfter; - - /** - * Constructs EditItem of a modification - * that was applied at position start and - * replaced CharSequence before with - * CharSequence after. - */ - public EditItem(int start, - CharSequence before, CharSequence after) { - mmStart = start; - mmBefore = before; - mmAfter = after; - } - } - //endregion - - - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.activity; + +import android.app.ProgressDialog; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.preference.PreferenceManager; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.MenuItemCompat; +import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.widget.ShareActionProvider; +import android.support.v7.widget.Toolbar; +import android.text.Editable; +import android.text.InputType; +import android.text.Selection; +import android.text.Spannable; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.KeyListener; +import android.text.style.ForegroundColorSpan; +import android.text.style.UnderlineSpan; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.EditText; +import android.widget.HorizontalScrollView; +import android.widget.ListView; +import android.widget.Toast; + +import com.faizmalkani.floatingactionbutton.FloatingActionButton; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.sufficientlysecure.rootcommands.Shell; +import org.sufficientlysecure.rootcommands.Toolbox; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.adapter.AdapterDrawer; +import sharedcode.turboeditor.dialogfragment.ChangelogDialog; +import sharedcode.turboeditor.dialogfragment.FileInfoDialog; +import sharedcode.turboeditor.dialogfragment.FindTextDialog; +import sharedcode.turboeditor.dialogfragment.NewFileDetailsDialog; +import sharedcode.turboeditor.dialogfragment.NumberPickerDialog; +import sharedcode.turboeditor.dialogfragment.SaveFileDialog; +import sharedcode.turboeditor.preferences.PreferenceHelper; +import sharedcode.turboeditor.task.SaveFileTask; +import sharedcode.turboeditor.texteditor.EditTextPadding; +import sharedcode.turboeditor.texteditor.FileUtils; +import sharedcode.turboeditor.texteditor.LineUtils; +import sharedcode.turboeditor.texteditor.PageSystem; +import sharedcode.turboeditor.texteditor.PageSystemButtons; +import sharedcode.turboeditor.texteditor.Patterns; +import sharedcode.turboeditor.texteditor.SearchResult; +import sharedcode.turboeditor.util.AccessStorageApi; +import sharedcode.turboeditor.util.AnimationUtils; +import sharedcode.turboeditor.util.AppInfoHelper; +import sharedcode.turboeditor.util.EventBusEvents; +import sharedcode.turboeditor.util.IHomeActivity; +import sharedcode.turboeditor.util.MimeTypes; +import sharedcode.turboeditor.util.ProCheckUtils; +import sharedcode.turboeditor.util.ThemeUtils; +import sharedcode.turboeditor.views.CustomDrawerLayout; +import sharedcode.turboeditor.views.DialogHelper; +import sharedcode.turboeditor.views.GoodScrollView; + +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.ENCODING; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.FONT_SIZE; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.LINE_NUMERS; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.MONOSPACE; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.READ_ONLY; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.SYNTAX; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.TEXT_SUGGESTIONS; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.WRAP_CONTENT; + +public abstract class MainActivity extends ActionBarActivity implements IHomeActivity, FindTextDialog + .SearchDialogInterface, GoodScrollView.ScrollInterface, PageSystem.PageSystemInterface, + PageSystemButtons.PageButtonsInterface, NumberPickerDialog.INumberPickerDialog, SaveFileDialog.ISaveDialog, + AdapterView.OnItemClickListener, AdapterDrawer.Callbacks{ + + //region VARIABLES + private static final int + ID_SELECT_ALL = android.R.id.selectAll; + private static final int ID_CUT = android.R.id.cut; + private static final int ID_COPY = android.R.id.copy; + private static final int ID_PASTE = android.R.id.paste; + private static final int SELECT_FILE_CODE = 121; + private static final int KITKAT_OPEN_REQUEST_CODE = 41; + private static final int SYNTAX_DELAY_MILLIS_SHORT = 250; + private static final int SYNTAX_DELAY_MILLIS_LONG = 1500; + private static final int ID_UNDO = R.id.im_undo; + private static final int ID_REDO = R.id.im_redo; + private static final int CHARS_TO_COLOR = 2500; + private static final Handler updateHandler = new Handler(); + private static final Runnable colorRunnable_duringEditing = + new Runnable() { + @Override + public void run() { + mEditor.replaceTextKeepCursor(null, true); + } + }; + private static final Runnable colorRunnable_duringScroll = + new Runnable() { + @Override + public void run() { + mEditor.replaceTextKeepCursor(null, false); + } + }; + private static boolean fileOpened = false; + private static String fileExtension; + /* + * This class provides a handy way to tie together the functionality of + * {@link DrawerLayout} and the framework ActionBar to implement the recommended + * design for navigation drawers. + */ + private static ActionBarDrawerToggle mDrawerToggle; + /* + * The Drawer Layout + */ + private static CustomDrawerLayout mDrawerLayout; + private static GoodScrollView verticalScroll; + private static String sFilePath = ""; + private static Editor mEditor; + private static HorizontalScrollView horizontalScroll; + private boolean searchingText; + private static SearchResult searchResult; + private static PageSystem pageSystem; + private static PageSystemButtons pageSystemButtons; + private static String currentEncoding = "UTF-8"; + private static Toolbar toolbar; + + /* + Navigation Drawer + */ + private static AdapterDrawer arrayAdapter; + private static LinkedList files; + //endregion + + //region Activity facts + + @Override + protected void onCreate(Bundle savedInstanceState) { + // set the windows background + ThemeUtils.setWindowsBackground(this); + // super!! + super.onCreate(savedInstanceState); + // setup the layout + setContentView(R.layout.activity_home); + toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar); + setSupportActionBar(toolbar); + // setup the navigation drawer + setupNavigationDrawer(); + // reset text editor + setupTextEditor(); + hideTextEditor(); + /* First Time we open this activity */ + if (savedInstanceState == null) { + // Open + mDrawerLayout.openDrawer(Gravity.START); + // Set the default title + getSupportActionBar().setTitle(getString(R.string.nome_app_turbo_editor)); + } + // parse the intent + parseIntent(getIntent()); + // show a dialog with the changelog + showChangeLog(); + } + + + @Override + protected final void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mDrawerToggle.syncState(); + } + + @Override + public void onResume() { + super.onResume(); + // Refresh the list view + refreshList(); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + parseIntent(intent); + } + + @Override + public void onPause() { + super.onPause(); + + if (PreferenceHelper.getAutoSave(getBaseContext()) && mEditor.canSaveFile()) { + saveTheFile(); + mEditor.fileSaved(); // so it doesn't ask to save in onDetach + } + } + + @Override + protected void onDestroy() { + try { + closeKeyBoard(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + super.onDestroy(); + } + + @Override + public final void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mDrawerToggle.onConfigurationChanged(newConfig); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + + if (keyCode == KeyEvent.KEYCODE_BACK) { + onBackPressed(); + return true; + } else if (keyCode == KeyEvent.KEYCODE_MENU) { + return false; + } else { + if (mEditor == null) + mEditor = (Editor) findViewById(R.id.editor); + + // this will happen on first key pressed on hard-keyboard only. Once myInputField + // gets the focus again, it will automatically receive further key presses. + + try { + if (fileOpened && mEditor != null && !mEditor.hasFocus()) { + mEditor.requestFocus(); + mEditor.onKeyDown(keyCode, event); + return true; + } + } catch (NullPointerException ex) { + + } + } + + + return false; + } + + @Override + public void onBackPressed() { + + try { + // if we should ignore the back button + if (PreferenceHelper.getIgnoreBackButton(this)) + return; + + if (mDrawerLayout.isDrawerOpen(Gravity.START) && fileOpened) { + mDrawerLayout.closeDrawer(Gravity.START); + } else if (mDrawerLayout.isDrawerOpen(Gravity.END) && fileOpened) { + mDrawerLayout.closeDrawer(Gravity.END); + } else if (fileOpened && mEditor.canSaveFile()) { + SaveFileDialog.newInstance(sFilePath, pageSystem.getAllText(mEditor + .getText().toString()), currentEncoding).show(getFragmentManager(), + "dialog"); + } else if (fileOpened) { + + // remove editor fragment + hideTextEditor(); + + // Set the default title + getSupportActionBar().setTitle(getString(R.string.nome_app_turbo_editor)); + + onEvent(new EventBusEvents.ClosedAFile()); + + mDrawerLayout.openDrawer(Gravity.START); + mDrawerLayout.closeDrawer(Gravity.END); + } else { + showInterstitial(); + super.onBackPressed(); + } + } catch (Exception e) { + // maybe something is null, who knows + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + String path = ""; + if (requestCode == SELECT_FILE_CODE) { + path = data.getStringExtra("path"); + if(TextUtils.isEmpty(path)) + path = AccessStorageApi.getPath(getBaseContext(), data.getData()); + } + + if (requestCode == KITKAT_OPEN_REQUEST_CODE) { + path = AccessStorageApi.getPath(getBaseContext(), data.getData()); + } + + if (!TextUtils.isEmpty(path)) { + File file = new File(path); + if (file.isFile() && file.exists()) { + onEvent(new EventBusEvents.NewFileToOpen(new File + (path))); + } + } + + } + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + // Path of the file selected + String filePath = files.get(position).getAbsolutePath(); + // Send the event that a file was selected + onEvent(new EventBusEvents.NewFileToOpen(new File(filePath))); + } + + //endregion + + //region MENU + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + if (fileOpened && searchingText) + getMenuInflater().inflate(R.menu.fragment_editor_search, menu); + else if (fileOpened) + getMenuInflater().inflate(R.menu.fragment_editor, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + + if (fileOpened && searchingText) { + MenuItem imReplace = menu.findItem(R.id.im_replace); + MenuItem imPrev = menu.findItem(R.id.im_previous_item); + MenuItem imNext = menu.findItem(R.id.im_next_item); + + if (imReplace != null) + imReplace.setVisible(searchResult.canReplaceSomething()); + + if (imPrev != null) + imPrev.setVisible(searchResult.hasPrevious()); + + if (imNext != null) + imNext.setVisible(searchResult.hasNext()); + + + } else if (fileOpened) { + MenuItem imSave = menu.findItem(R.id.im_save); + MenuItem imUndo = menu.findItem(R.id.im_undo); + MenuItem imRedo = menu.findItem(R.id.im_redo); + if (mEditor != null) { + if (imSave != null) + imSave.setVisible(mEditor.canSaveFile()); + if (imUndo != null) + imUndo.setVisible(mEditor.getCanUndo()); + if (imRedo != null) + imRedo.setVisible(mEditor.getCanRedo()); + } else { + imSave.setVisible(false); + imUndo.setVisible(false); + imRedo.setVisible(false); + } + + MenuItem item = menu.findItem(R.id.im_share); + ShareActionProvider shareAction = (ShareActionProvider) MenuItemCompat + .getActionProvider(item); + File f = new File(sFilePath); + Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f)); + shareIntent.setType("text/plain"); + shareAction.setShareIntent(shareIntent); + } + + MenuItem imDonate = menu.findItem(R.id.im_donate); + if (imDonate != null) + if (ProCheckUtils.isPro(this, false)) + imDonate.setVisible(false); + + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int i = item.getItemId(); + if (mDrawerToggle.onOptionsItemSelected(item)) { + Toast.makeText(getBaseContext(), "drawer click", Toast.LENGTH_SHORT).show(); + mDrawerLayout.closeDrawer(Gravity.END); + return true; + } else if (i == R.id.im_save) { + saveTheFile(); + + } else if (i == R.id.im_undo) { + mEditor.onTextContextMenuItem(ID_UNDO); + + } else if (i == R.id.im_redo) { + mEditor.onTextContextMenuItem(ID_REDO); + + } else if (i == R.id.im_search) { + FindTextDialog.newInstance(mEditor.getText().toString()).show(getFragmentManager() + .beginTransaction(), "dialog"); + } else if (i == R.id.im_cancel) { + searchingText = false; + invalidateOptionsMenu(); + + } else if (i == R.id.im_replace) { + replaceText(); + + } else if (i == R.id.im_next_item) { + nextResult(); + + } else if (i == R.id.im_previous_item) { + previousResult(); + + } else if (i == R.id.im_goto_line) { + int min = mEditor.getLineUtils().firstReadLine(); + int max = mEditor.getLineUtils().lastReadLine(); + NumberPickerDialog.newInstance + (NumberPickerDialog.Actions.GoToLine, min, min, max).show(getFragmentManager().beginTransaction(), "dialog"); + } else if (i == R.id.im_view_it_on_browser) { + Intent browserIntent; + try { + browserIntent = new Intent(Intent.ACTION_VIEW); + browserIntent.setDataAndType(Uri.fromFile(new File(sFilePath)), "text/*"); + startActivity(browserIntent); + } catch (ActivityNotFoundException ex2) { + // + } + + } else if (i == R.id.im_info) { + FileInfoDialog.newInstance(sFilePath).show(getFragmentManager().beginTransaction(), "dialog"); + } + + else if (i == R.id.im_donate) { + DialogHelper.showDonateDialog(this); + } + return super.onOptionsItemSelected(item); + } + //endregion + + // region OTHER THINGS + void replaceText() { + int start = searchResult.foundIndex.get(searchResult.index); + int end = start + searchResult.textLength; + mEditor.setText(mEditor.getText().replace(start, end, searchResult.textToReplace)); + searchResult.doneReplace(); + + invalidateOptionsMenu(); + + if (searchResult.hasNext()) + nextResult(); + else if (searchResult.hasPrevious()) + previousResult(); + } + + void nextResult() { + if (searchResult.index == mEditor.getLineCount() - 1) // last result of page + { + return; + } + + + if (searchResult.index < searchResult.numberOfResults() - 1) { // equal zero is not good + searchResult.index++; + final int line = mEditor.getLineUtils().getLineFromIndex(searchResult.foundIndex.get + (searchResult.index), mEditor.getLineCount(), mEditor.getLayout()); + + + verticalScroll.post(new Runnable() { + @Override + public void run() { + int y = mEditor.getLayout().getLineTop(line); + if (y > 100) + y -= 100; + else + y = 0; + + verticalScroll.scrollTo(0, y); + } + }); + + mEditor.setFocusable(true); + mEditor.requestFocus(); + mEditor.setSelection(searchResult.foundIndex.get(searchResult.index), + searchResult.foundIndex.get(searchResult.index) + searchResult.textLength); + } + + invalidateOptionsMenu(); + } + + void previousResult() { + if (searchResult.index == 0) + return; + if (searchResult.index > 0) { + searchResult.index--; + final int line = LineUtils.getLineFromIndex(searchResult.foundIndex.get + (searchResult.index), mEditor.getLineCount(), mEditor.getLayout()); + verticalScroll.post(new Runnable() { + @Override + public void run() { + int y = mEditor.getLayout().getLineTop(line); + if (y > 100) + y -= 100; + else + y = 0; + verticalScroll.scrollTo(0, y); + } + }); + + mEditor.setFocusable(true); + mEditor.requestFocus(); + mEditor.setSelection(searchResult.foundIndex.get(searchResult.index), + searchResult.foundIndex.get(searchResult.index) + searchResult.textLength); + } + + invalidateOptionsMenu(); + } + + private void saveTheFile() { + File file = new File(sFilePath); + if (!file.getName().isEmpty()) + new SaveFileTask(this, sFilePath, pageSystem.getAllText(mEditor.getText() + .toString()), currentEncoding).execute(); + else { + NewFileDetailsDialog.newInstance + (pageSystem.getAllText(mEditor.getText().toString()), currentEncoding).show(getFragmentManager().beginTransaction(), "dialog"); + } + } + + /** + * Setup the navigation drawer + */ + private void setupNavigationDrawer() { + mDrawerLayout = (CustomDrawerLayout) findViewById(R.id.drawer_layout); + /* Action Bar + final ActionBar ab = toolbar; + ab.setDisplayHomeAsUpEnabled(true); + ab.setHomeButtonEnabled(true);*/ + /* Navigation drawer */ + mDrawerToggle = + new ActionBarDrawerToggle( + this, + mDrawerLayout, + toolbar, + R.string.nome_app_turbo_editor, + R.string.nome_app_turbo_editor) { + + @Override + public void onDrawerOpened(View drawerView) { + supportInvalidateOptionsMenu(); + try { + closeKeyBoard(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + } + + @Override + public void onDrawerClosed(View view) { + supportInvalidateOptionsMenu(); + } + }; + /* link the mDrawerToggle to the Drawer Layout */ + mDrawerLayout.setDrawerListener(mDrawerToggle); +//mDrawerLayout.setFocusableInTouchMode(false); + + ListView listView = (ListView) findViewById(android.R.id.list); + listView.setEmptyView(findViewById(android.R.id.empty)); + files = new LinkedList<>(); + arrayAdapter = new AdapterDrawer(this, files, this); + listView.setAdapter(arrayAdapter); + listView.setOnItemClickListener(this); + } + + private void setupTextEditor() { + + verticalScroll = (GoodScrollView) findViewById(R.id.vertical_scroll); + horizontalScroll = (HorizontalScrollView) findViewById(R.id.horizontal_scroll); + mEditor = (Editor) findViewById(R.id.editor); + + //mEditor.setLayerType(View.LAYER_TYPE_NONE, null); + + if (PreferenceHelper.getWrapContent(this)) { + horizontalScroll.removeView(mEditor); + verticalScroll.removeView(horizontalScroll); + verticalScroll.addView(mEditor); + } + + if (PreferenceHelper.getReadOnly(this)) { + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); + } else { + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + } + + verticalScroll.setScrollInterface(this); + + pageSystem = new PageSystem(this, this, "", null); + + pageSystemButtons = new PageSystemButtons(this, this, + (FloatingActionButton) findViewById(R.id.fabPrev), + (FloatingActionButton) findViewById(R.id.fabNext)); + } + + private void showTextEditor() { + + fileOpened = true; + + findViewById(R.id.text_editor).setVisibility(View.VISIBLE); + findViewById(R.id.no_file_opened_messagge).setVisibility(View.GONE); + + mEditor.resetVariables(); + searchResult = null; + searchingText = false; + + invalidateOptionsMenu(); + + mEditor.disableTextChangedListener(); + mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText(), false); + mEditor.enableTextChangedListener(); + } + + private void hideTextEditor() { + + fileOpened = false; + + try { + findViewById(R.id.text_editor).setVisibility(View.GONE); + findViewById(R.id.no_file_opened_messagge).setVisibility(View.VISIBLE); + + mEditor.disableTextChangedListener(); + mEditor.replaceTextKeepCursor("", false); + mEditor.enableTextChangedListener(); + } catch (Exception e) { + // lol + } + } + + /** + * Parses the intent + */ + private void parseIntent(Intent intent) { + final String action = intent.getAction(); + final String type = intent.getType(); + + if (Intent.ACTION_VIEW.equals(action) + || Intent.ACTION_EDIT.equals(action) + || Intent.ACTION_PICK.equals(action) + && type != null) { + // Post event + onEvent(new EventBusEvents.NewFileToOpen(new File(intent + .getData().getPath()))); + } else if (Intent.ACTION_SEND.equals(action) && type != null) { + if ("text/plain".equals(type)) { + onEvent(new EventBusEvents.NewFileToOpen(intent.getStringExtra(Intent.EXTRA_TEXT))); + } + } + } + + /** + * Show a dialog with the changelog + */ + private void showChangeLog() { + final String currentVersion = AppInfoHelper.getCurrentVersion(this); + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + final String lastVersion = preferences.getString("last_version", currentVersion); + preferences.edit().putString("last_version", currentVersion).apply(); + if (!lastVersion.equals(currentVersion)) { + ChangelogDialog.showChangeLogDialog(getFragmentManager()); + } + } + + // closes the soft keyboard + private void closeKeyBoard() throws NullPointerException { + // Central system API to the overall input method framework (IMF) architecture + InputMethodManager inputManager = + (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + + // Base interface for a remotable object + IBinder windowToken = getCurrentFocus().getWindowToken(); + + // Hide type + int hideType = InputMethodManager.HIDE_NOT_ALWAYS; + + // Hide the KeyBoard + inputManager.hideSoftInputFromWindow(windowToken, hideType); + } + + void updateTextSyntax() { + if (!PreferenceHelper.getSyntaxHighlight(this) || mEditor.hasSelection() || + updateHandler == null || colorRunnable_duringEditing == null) + return; + + updateHandler.removeCallbacks(colorRunnable_duringEditing); + updateHandler.removeCallbacks(colorRunnable_duringScroll); + updateHandler.postDelayed(colorRunnable_duringEditing, SYNTAX_DELAY_MILLIS_LONG); + } + + private void refreshList(){ + refreshList(null, false, false); + } + + private void refreshList(@Nullable String path, boolean add, boolean delete) { + int max_recent_files = 15; + if(add) + max_recent_files--; + + // File paths saved in preferences + String[] savedPaths = PreferenceHelper.getSavedPaths(this); + int first_index_of_array = savedPaths.length > max_recent_files ? savedPaths.length - max_recent_files : 0; + savedPaths = ArrayUtils.subarray(savedPaths, first_index_of_array, savedPaths.length); + // File names for the list + files.clear(); + // StringBuilder that will contain the file paths + StringBuilder sb = new StringBuilder(); + // for cycle to convert paths to names + + for(int i = 0; i < savedPaths.length; i++){ + String savedPath = savedPaths[i]; + File file = new File(savedPath); + // Check that the file exist + if (file.exists()) { + if(path != null && path.equals(savedPath) && delete) + continue; + else { + files.addFirst(file); + sb.append(savedPath).append(","); + } + } + } + if(path != null && !path.isEmpty() && add && !ArrayUtils.contains(savedPaths, path)) { + sb.append(path).append(","); + files.addFirst(new File(path)); + } + // save list without empty or non existed files + PreferenceHelper.setSavedPaths(this, sb); + // Set adapter + arrayAdapter.notifyDataSetChanged(); + } + //endregion + + //region EVENTBUS + void onEvent(final EventBusEvents.NewFileToOpen event) { + + if (fileOpened && mEditor.canSaveFile()) { + SaveFileDialog.newInstance(sFilePath, pageSystem.getAllText(mEditor + .getText().toString()), currentEncoding, true, event.getFile().getAbsolutePath()).show(getFragmentManager(), + "dialog"); + return; + } + + new AsyncTask() { + + File file; + String message = ""; + String fileText; + String encoding; + ProgressDialog progressDialog; + + @Override + protected void onPreExecute() { + super.onPreExecute(); + // Close the drawer + mDrawerLayout.closeDrawer(Gravity.START); + progressDialog = new ProgressDialog(MainActivity.this); + progressDialog.setMessage(getString(R.string.please_wait)); + progressDialog.show(); + + } + + @Override + protected Void doInBackground(Void... params) { + file = event.getFile(); + try { + if (!file.exists() || !file.isFile()) { + fileText = event.getFileText(); + sFilePath = file.getAbsolutePath(); + fileExtension = "txt"; + return null; + } + + file = file.getCanonicalFile(); + sFilePath = file.getAbsolutePath(); + fileExtension = FilenameUtils.getExtension(sFilePath).toLowerCase(); + + boolean isRoot; + + if (!file.canRead()) { + Shell shell; + shell = Shell.startRootShell(); + Toolbox tb = new Toolbox(shell); + isRoot = tb.isRootAccessGiven(); + + if (isRoot) { + File tempFile = new File(getFilesDir(), "temp.root.file"); + if (!tempFile.exists()) + tempFile.createNewFile(); + tb.copyFile(event.getFile().getAbsolutePath(), + tempFile.getAbsolutePath(), false, false); + file = new File(tempFile.getAbsolutePath()); + } + } + + boolean autoencoding = PreferenceHelper.getAutoEncoding(MainActivity.this); + if (autoencoding) { + + encoding = FileUtils.getDetectedEncoding(file); + if (encoding.isEmpty()) { + encoding = PreferenceHelper.getEncoding(MainActivity.this); + } + } else { + encoding = PreferenceHelper.getEncoding(MainActivity.this); + } + + fileText = org.apache.commons.io.FileUtils.readFileToString(file, encoding); + } catch (Exception e) { + message = e.getMessage(); + fileText = ""; + } + + while (mDrawerLayout.isDrawerOpen(Gravity.START)) { + try { + Thread.sleep(50); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + super.onPostExecute(result); + progressDialog.hide(); + + if (!message.isEmpty()) { + Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show(); + onEvent(new EventBusEvents.CannotOpenAFile()); + } else { + + pageSystem = new PageSystem(MainActivity.this, MainActivity.this, fileText, new File(sFilePath)); + currentEncoding = encoding; + + onEvent(new EventBusEvents.AFileIsSelected(sFilePath)); + + showTextEditor(); + + String name = FilenameUtils.getName(sFilePath); + if (name.isEmpty()) + getSupportActionBar().setTitle(R.string.new_file); + else + getSupportActionBar().setTitle(name); + + if(!name.isEmpty()) { + refreshList(sFilePath, true, false); + } + } + + } + }.execute(); + } + + public void onEvent(EventBusEvents.SavedAFile event) { + + sFilePath = event.getPath(); + fileExtension = FilenameUtils.getExtension(sFilePath).toLowerCase(); + + mEditor.clearHistory(); + mEditor.fileSaved(); + invalidateOptionsMenu(); + + try { + closeKeyBoard(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + refreshList(event.getPath(), true, false); + arrayAdapter.selectView(event.getPath()); + + showInterstitial(); + } + + /** + * When a file can't be opened + * Invoked by the EditorFragment + * + * @param event The event called + */ + void onEvent(EventBusEvents.CannotOpenAFile event) { + // + mDrawerLayout.openDrawer(Gravity.LEFT); + // + getSupportActionBar().setTitle(getString(R.string.nome_app_turbo_editor)); + // + supportInvalidateOptionsMenu(); + // Replace fragment + hideTextEditor(); + } + + public void onEvent(EventBusEvents.APreferenceValueWasChanged event) { + + if (event.hasType(EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE)) { + ThemeUtils.setWindowsBackground(this); + } + + if (event.hasType(WRAP_CONTENT)) { + if (PreferenceHelper.getWrapContent(this)) { + horizontalScroll.removeView(mEditor); + verticalScroll.removeView(horizontalScroll); + verticalScroll.addView(mEditor); + } else { + verticalScroll.removeView(mEditor); + verticalScroll.addView(horizontalScroll); + horizontalScroll.addView(mEditor); + } + } else if (event.hasType(LINE_NUMERS)) { + mEditor.disableTextChangedListener(); + mEditor.replaceTextKeepCursor(null, true); + mEditor.enableTextChangedListener(); + if (PreferenceHelper.getLineNumbers(this)) { + mEditor.setPadding(EditTextPadding.getPaddingWithLineNumbers(this, + PreferenceHelper.getFontSize(this)), + EditTextPadding.getPaddingTop(this), 0, 0); + } else { + mEditor.setPadding(EditTextPadding.getPaddingWithoutLineNumbers(this) + , EditTextPadding.getPaddingTop(this), 0, 0); + } + } else if (event.hasType(SYNTAX)) { + mEditor.disableTextChangedListener(); + mEditor.replaceTextKeepCursor(null, true); + mEditor.enableTextChangedListener(); + } else if (event.hasType(MONOSPACE)) { + if (PreferenceHelper.getUseMonospace(this)) + mEditor.setTypeface(Typeface.MONOSPACE); + else + mEditor.setTypeface(Typeface.DEFAULT); + } else if (event.hasType(THEME_CHANGE)) { + if (PreferenceHelper.getLightTheme(this)) { + mEditor.setTextColor(getResources().getColor(R.color.textColorInverted)); + } else { + mEditor.setTextColor(getResources().getColor(R.color.textColor)); + } + } else if (event.hasType(TEXT_SUGGESTIONS) || event.hasType(READ_ONLY)) { + if (PreferenceHelper.getReadOnly(this)) { + getWindow().setSoftInputMode(WindowManager.LayoutParams + .SOFT_INPUT_STATE_ALWAYS_HIDDEN); + mEditor.setReadOnly(true); + } else { + getWindow().setSoftInputMode(WindowManager.LayoutParams + .SOFT_INPUT_STATE_UNSPECIFIED); + mEditor.setReadOnly(false); + if (PreferenceHelper.getSuggestionActive(this)) { + mEditor.setInputType(InputType.TYPE_CLASS_TEXT | InputType + .TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE); + } else { + mEditor.setInputType(InputType.TYPE_CLASS_TEXT | InputType + .TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS + | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType + .TYPE_TEXT_FLAG_IME_MULTI_LINE); + } + } + // sometimes it becomes monospace after setting the input type + if (PreferenceHelper.getUseMonospace(this)) + mEditor.setTypeface(Typeface.MONOSPACE); + else + mEditor.setTypeface(Typeface.DEFAULT); + } else if (event.hasType(FONT_SIZE)) { + if (PreferenceHelper.getLineNumbers(this)) { + mEditor.setPadding(EditTextPadding.getPaddingWithLineNumbers(this, + PreferenceHelper.getFontSize(this)), + EditTextPadding.getPaddingTop(this), 0, 0); + } else { + mEditor.setPadding(EditTextPadding.getPaddingWithoutLineNumbers(this) + , EditTextPadding.getPaddingTop(this), 0, 0); + } + mEditor.setTextSize(PreferenceHelper.getFontSize(this)); + } else if (event.hasType(ENCODING)) { + String oldEncoding, newEncoding; + oldEncoding = currentEncoding; + newEncoding = PreferenceHelper.getEncoding(this); + try { + final byte[] oldText = mEditor.getText().toString().getBytes(oldEncoding); + mEditor.disableTextChangedListener(); + mEditor.replaceTextKeepCursor(new String(oldText, newEncoding), true); + mEditor.enableTextChangedListener(); + currentEncoding = newEncoding; + } catch (UnsupportedEncodingException ignored) { + try { + final byte[] oldText = mEditor.getText().toString().getBytes(oldEncoding); + mEditor.disableTextChangedListener(); + mEditor.replaceTextKeepCursor(new String(oldText, "UTF-8"), true); + mEditor.enableTextChangedListener(); + } catch (UnsupportedEncodingException ignored2) { + } + } + } + } + + void onEvent(EventBusEvents.AFileIsSelected event) { + arrayAdapter.selectView(event.getPath()); + } + + void onEvent(EventBusEvents.ClosedAFile event) { + arrayAdapter.selectView(""); + } + //endregion + + //region Calls from the layout + public void OpenFile(View view) { + Intent subActivity = new Intent(MainActivity.this, SelectFileActivity.class); + subActivity.putExtra("action", SelectFileActivity.Actions.SelectFile); + AnimationUtils.startActivityWithScale(this, subActivity, true, SELECT_FILE_CODE, view); + } + + public void CreateFile(View view) { + onEvent(new EventBusEvents.NewFileToOpen("")); // do not send the event to others + } + + public void OpenInfo(View view) { + DialogHelper.showAboutDialog(this); + } + + public void OpenSettings(View view) { + mDrawerLayout.closeDrawer(Gravity.START); + mDrawerLayout.openDrawer(Gravity.END); + } + //endregion + + //region Ovverideses + @Override + public void nextPageClicked() { + pageSystem.savePage(mEditor.getText().toString()); + pageSystem.nextPage(); + mEditor.disableTextChangedListener(); + mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText(), false); + mEditor.enableTextChangedListener(); + + verticalScroll.postDelayed(new Runnable() { + @Override + public void run() { + verticalScroll.smoothScrollTo(0, 0); + } + }, 200); + + if (!PreferenceHelper.getPageSystemButtonsPopupShown(this)) { + PreferenceHelper.setPageSystemButtonsPopupShown(this, true); + Toast.makeText(this, getString(R.string.long_click_for_more_options), + Toast.LENGTH_LONG).show(); + } + } + + @Override + public void prevPageClicked() { + pageSystem.savePage(mEditor.getText().toString()); + pageSystem.prevPage(); + mEditor.disableTextChangedListener(); + mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText(), false); + mEditor.enableTextChangedListener(); + + verticalScroll.postDelayed(new Runnable() { + @Override + public void run() { + verticalScroll.smoothScrollTo(0, 0); + } + }, 200); + + if (!PreferenceHelper.getPageSystemButtonsPopupShown(this)) { + PreferenceHelper.setPageSystemButtonsPopupShown(this, true); + Toast.makeText(this, getString(R.string.long_click_for_more_options), + Toast.LENGTH_LONG).show(); + } + } + + @Override + public void pageSystemButtonLongClicked() { + int maxPages = pageSystem.getMaxPage(); + int currentPage = pageSystem.getCurrentPage(); + NumberPickerDialog.newInstance + (NumberPickerDialog.Actions.SelectPage, 0, currentPage, maxPages).show(getFragmentManager().beginTransaction(), "dialog"); + } + + @Override + public boolean canReadNextPage() { + return pageSystem.canReadNextPage(); + } + + @Override + public boolean canReadPrevPage() { + return pageSystem.canReadPrevPage(); + } + + @Override + public void onSearchDone(SearchResult searchResult) { + MainActivity.searchResult = searchResult; + searchingText = true; + invalidateOptionsMenu(); + + final int line = LineUtils.getLineFromIndex(searchResult.foundIndex.getFirst + (), mEditor.getLineCount(), mEditor.getLayout()); + verticalScroll.post(new Runnable() { + @Override + public void run() { + int y = mEditor.getLayout().getLineTop(line); + if (y > 100) + y -= 100; + else + y = 0; + + verticalScroll.scrollTo(0, y); + } + }); + + mEditor.setFocusable(true); + mEditor.requestFocus(); + mEditor.setSelection(searchResult.foundIndex.getFirst(), searchResult.foundIndex.getFirst + () + searchResult.textLength); + + } + + @Override + public void onPageChanged(int page) { + pageSystemButtons.updateVisibility(false); + searchingText = false; + mEditor.clearHistory(); + invalidateOptionsMenu(); + } + + @Override + public void onScrollChanged(int l, int t, int oldl, int oldt) { + pageSystemButtons.updateVisibility(Math.abs(t) > 10); + + if (!PreferenceHelper.getSyntaxHighlight(this) || (mEditor.hasSelection() && + !searchingText) || updateHandler == null || colorRunnable_duringScroll == null) + return; + + updateHandler.removeCallbacks(colorRunnable_duringEditing); + updateHandler.removeCallbacks(colorRunnable_duringScroll); + updateHandler.postDelayed(colorRunnable_duringScroll, SYNTAX_DELAY_MILLIS_SHORT); + } + + @Override + public void onNumberPickerDialogDismissed(NumberPickerDialog.Actions action, int value) { + if (action == NumberPickerDialog.Actions.SelectPage) { + pageSystem.savePage(mEditor.getText().toString()); + pageSystem.goToPage(value); + mEditor.disableTextChangedListener(); + mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText(), true); + mEditor.enableTextChangedListener(); + + verticalScroll.postDelayed(new Runnable() { + @Override + public void run() { + verticalScroll.smoothScrollTo(0, 0); + } + }, 200); + + } else if (action == NumberPickerDialog.Actions.GoToLine) { + + int fakeLine = mEditor.getLineUtils().fakeLineFromRealLine(value); + final int y = mEditor.getLineUtils().getYAtLine(verticalScroll, + mEditor.getLineCount(), fakeLine); + + verticalScroll.postDelayed(new Runnable() { + @Override + public void run() { + verticalScroll.smoothScrollTo(0, y); + } + }, 200); + } + + } + + @Override + public void userDoesntWantToSave(boolean openNewFile, String pathOfNewFile) { + Editor.canSaveFile = false; + if(openNewFile) + onEvent(new EventBusEvents.NewFileToOpen(new File(pathOfNewFile))); + else + onEvent(new EventBusEvents.CannotOpenAFile()); + } + + @Override + public void CancelItem(int position, boolean andCloseOpenedFile) { + refreshList(files.get(position).getAbsolutePath(), false, true); + if (andCloseOpenedFile) + onEvent(new EventBusEvents.CannotOpenAFile()); + } + //endregion + + public static class Editor extends EditText { + + //region VARIABLES + private static final TextPaint mPaintNumbers = new TextPaint(); + /** + * The edit history. + */ + private final EditHistory mEditHistory; + /** + * The change listener. + */ + private final EditTextChangeListener + mChangeListener; + /** + * Disconnect this undo/redo from the text + * view. + */ + private static boolean enabledChangeListener; + private static int paddingTop; + private static int numbersWidth; + private static int lineHeight; + + private static int lineCount, realLine, startingLine; + private static LineUtils lineUtils; + /** + * Is undo/redo being performed? This member + * signals if an undo/redo operation is + * currently being performed. Changes in the + * text during undo/redo are not recorded + * because it would mess up the undo history. + */ + private static boolean mIsUndoOrRedo; + private static Matcher m; + private static boolean mShowUndo, mShowRedo; + private static boolean canSaveFile; + private static KeyListener keyListener; + private static int firstVisibleIndex, firstColoredIndex; + private static int deviceHeight; + private static int editorHeight; + private static boolean[] hasNewLineArray; + private static int[] realLines; + private static boolean wrapContent; + private static int lastLine; + private static int firstLine; + private static CharSequence textToHighlight; + private static int lastVisibleIndex; + private static int i; + //endregion + + //region CONSTRUCTOR + public Editor(final Context context, AttributeSet attrs) { + super(context, attrs); + + //setLayerType(View.LAYER_TYPE_NONE, null); + + mEditHistory = new EditHistory(); + mChangeListener = new EditTextChangeListener(); + lineUtils = new LineUtils(); + + deviceHeight = getResources().getDisplayMetrics().heightPixels; + + paddingTop = EditTextPadding.getPaddingTop(getContext()); + + mPaintNumbers.setAntiAlias(true); + mPaintNumbers.setDither(false); + mPaintNumbers.setTextAlign(Paint.Align.RIGHT); + mPaintNumbers.setColor(getResources().getColor(R.color.file_text)); + + if (PreferenceHelper.getLightTheme(getContext())) { + setTextColor(getResources().getColor(R.color.textColorInverted)); + } else { + setTextColor(getResources().getColor(R.color.textColor)); + } + if (PreferenceHelper.getLineNumbers(getContext())) { + setPadding(EditTextPadding.getPaddingWithLineNumbers(getContext(), + PreferenceHelper.getFontSize(getContext())), + EditTextPadding.getPaddingTop(getContext()), 0, 0); + } else { + setPadding(EditTextPadding.getPaddingWithoutLineNumbers(getContext()), + EditTextPadding.getPaddingTop(getContext()), 0, 0); + } + + if (PreferenceHelper.getReadOnly(getContext())) { + setReadOnly(true); + } else { + setReadOnly(false); + if (PreferenceHelper.getSuggestionActive(getContext())) { + setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE + | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE); + } else { + setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType + .TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType + .TYPE_TEXT_FLAG_IME_MULTI_LINE); + } + } + + if (PreferenceHelper.getUseMonospace(getContext())) { + setTypeface(Typeface.MONOSPACE); + } else { + setTypeface(Typeface.DEFAULT); + } + setTextSize(PreferenceHelper.getFontSize(getContext())); + + setFocusable(true); + setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!PreferenceHelper.getReadOnly(getContext())) { + verticalScroll.tempDisableListener(1000); + ((InputMethodManager) getContext().getSystemService(Context + .INPUT_METHOD_SERVICE)) + .showSoftInput(Editor.this, InputMethodManager.SHOW_IMPLICIT); + } + + } + }); + setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus && !PreferenceHelper.getReadOnly(getContext())) { + verticalScroll.tempDisableListener(1000); + ((InputMethodManager) getContext().getSystemService(Context + .INPUT_METHOD_SERVICE)) + .showSoftInput(Editor.this, InputMethodManager.SHOW_IMPLICIT); + } + } + }); + + setMaxHistorySize(30); + + resetVariables(); + } + + public void setReadOnly(boolean value) { + if (value) { + keyListener = getKeyListener(); + setKeyListener(null); + } else { + if (keyListener != null) + setKeyListener(keyListener); + } + } + + //region OVERRIDES + @Override + public void setTextSize(float size) { + super.setTextSize(size); + final float scale = getContext().getResources().getDisplayMetrics().density; + mPaintNumbers.setTextSize((int) (size * scale * 0.65f)); + numbersWidth = (int) (EditTextPadding.getPaddingWithLineNumbers(getContext(), + PreferenceHelper.getFontSize(getContext())) * 0.8); + lineHeight = getLineHeight(); + } + + + @Override + public void onDraw(@NonNull final Canvas canvas) { + + if (lineCount != getLineCount() || startingLine != pageSystem.getStartingLine()) { + startingLine = pageSystem.getStartingLine(); + lineCount = getLineCount(); + lineUtils.updateHasNewLineArray(pageSystem + .getStartingLine(), lineCount, getLayout(), getText().toString()); + + hasNewLineArray = lineUtils.getToCountLinesArray(); + realLines = lineUtils.getRealLines(); + + } + + editorHeight = getHeight(); + firstLine = lineUtils.getFirstVisibleLine(verticalScroll, editorHeight, lineCount); + lastLine = lineUtils.getLastVisibleLine(verticalScroll, editorHeight, lineCount, deviceHeight); + + if (PreferenceHelper.getLineNumbers(getContext())) { + wrapContent = PreferenceHelper.getWrapContent(getContext()); + i = firstLine; + + while (i < lastLine) { + // if last line we count it anyway + if (!wrapContent + || hasNewLineArray[i] + || i == lastLine - 1) { + realLine = realLines[i]; + + canvas.drawText(String.valueOf(realLine), + numbersWidth, // they are all center aligned + paddingTop + lineHeight * (i + 1), + mPaintNumbers); + } + i++; + } + } + + super.onDraw(canvas); + } + + + //endregion + + //region Other + + @Override + public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { + + if (event.isCtrlPressed()) { + switch (keyCode) { + case KeyEvent.KEYCODE_A: + return onTextContextMenuItem(ID_SELECT_ALL); + case KeyEvent.KEYCODE_X: + return onTextContextMenuItem(ID_CUT); + case KeyEvent.KEYCODE_C: + return onTextContextMenuItem(ID_COPY); + case KeyEvent.KEYCODE_V: + return onTextContextMenuItem(ID_PASTE); + case KeyEvent.KEYCODE_Z: + if (getCanUndo()) { + return onTextContextMenuItem(ID_UNDO); + } + case KeyEvent.KEYCODE_Y: + if (getCanRedo()) { + return onTextContextMenuItem(ID_REDO); + } + case KeyEvent.KEYCODE_S: + ((MainActivity) getContext()).saveTheFile(); + return true; + default: + return super.onKeyDown(keyCode, event); + } + } else { + switch (keyCode) { + case KeyEvent.KEYCODE_TAB: + String textToInsert = " "; + int start, end; + start = Math.max(getSelectionStart(), 0); + end = Math.max(getSelectionEnd(), 0); + getText().replace(Math.min(start, end), Math.max(start, end), + textToInsert, 0, textToInsert.length()); + return true; + default: + return super.onKeyDown(keyCode, event); + } + } + } + + @Override + public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) { + if (event.isCtrlPressed()) { + switch (keyCode) { + case KeyEvent.KEYCODE_A: + case KeyEvent.KEYCODE_X: + case KeyEvent.KEYCODE_C: + case KeyEvent.KEYCODE_V: + case KeyEvent.KEYCODE_Z: + case KeyEvent.KEYCODE_Y: + case KeyEvent.KEYCODE_S: + return true; + default: + return false; + } + } else { + switch (keyCode) { + case KeyEvent.KEYCODE_TAB: + return true; + default: + return false; + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean onTextContextMenuItem( + final int id) { + if (id == ID_UNDO) { + undo(); + return true; + } else if (id == ID_REDO) { + redo(); + return true; + } else { + return super.onTextContextMenuItem(id); + } + } + + /** + * Can undo be performed? + */ + public boolean getCanUndo() { + return (mEditHistory.mmPosition > 0); + } + + /** + * Can redo be performed? + */ + public boolean getCanRedo() { + return (mEditHistory.mmPosition + < mEditHistory.mmHistory.size()); + } + + /** + * Perform undo. + */ + public void undo() { + EditItem edit = mEditHistory.getPrevious(); + if (edit == null) { + return; + } + + Editable text = getEditableText(); + int start = edit.mmStart; + int end = start + (edit.mmAfter != null + ? edit.mmAfter.length() : 0); + + mIsUndoOrRedo = true; + text.replace(start, end, edit.mmBefore); + mIsUndoOrRedo = false; + + // This will get rid of underlines inserted when editor tries to come + // up with a suggestion. + for (Object o : text.getSpans(0, + text.length(), UnderlineSpan.class)) { + text.removeSpan(o); + } + + Selection.setSelection(text, + edit.mmBefore == null ? start + : (start + edit.mmBefore.length())); + } + + /** + * Perform redo. + */ + public void redo() { + EditItem edit = mEditHistory.getNext(); + if (edit == null) { + return; + } + + Editable text = getEditableText(); + int start = edit.mmStart; + int end = start + (edit.mmBefore != null + ? edit.mmBefore.length() : 0); + + mIsUndoOrRedo = true; + text.replace(start, end, edit.mmAfter); + mIsUndoOrRedo = false; + + // This will get rid of underlines inserted when editor tries to come + // up with a suggestion. + for (Object o : text.getSpans(0, + text.length(), UnderlineSpan.class)) { + text.removeSpan(o); + } + + Selection.setSelection(text, + edit.mmAfter == null ? start + : (start + edit.mmAfter.length())); + } + + /** + * Set the maximum history size. If size is + * negative, then history size is only limited + * by the device memory. + */ + public void setMaxHistorySize( + int maxHistorySize) { + mEditHistory.setMaxHistorySize( + maxHistorySize); + } + + public void resetVariables() { + mEditHistory.clear(); + enabledChangeListener = false; + lineCount = 0; + realLine = 0; + startingLine = 0; + mIsUndoOrRedo = false; + mShowUndo = false; + mShowRedo = false; + canSaveFile = false; + firstVisibleIndex = 0; + firstColoredIndex = 0; + } + + public boolean canSaveFile() { + return canSaveFile; + } + + public void fileSaved() { + canSaveFile = false; + } + + public void replaceTextKeepCursor(String textToUpdate, boolean mantainCursorPos) { + + int cursorPos; + int cursorPosEnd; + if (textToUpdate != null) { + cursorPos = 0; + cursorPosEnd = 0; + } else { + cursorPos = getSelectionStart(); + cursorPosEnd = getSelectionEnd(); + } + disableTextChangedListener(); + + if (PreferenceHelper.getSyntaxHighlight(getContext())) + setText(highlight(textToUpdate == null ? getEditableText() : Editable.Factory + .getInstance().newEditable(textToUpdate), textToUpdate != null)); + else + setText(textToUpdate == null ? getText().toString() : textToUpdate); + + enableTextChangedListener(); + + if (mantainCursorPos) + firstVisibleIndex = cursorPos; + + if (firstVisibleIndex > -1) { + if (cursorPosEnd != cursorPos) + setSelection(cursorPos, cursorPosEnd); + else + setSelection(firstVisibleIndex); + } + } + //endregion + + //region UNDO REDO + + public void disableTextChangedListener() { + enabledChangeListener = false; + removeTextChangedListener(mChangeListener); + } + + public CharSequence highlight(Editable editable, boolean newText) { + editable.clearSpans(); + + if (editable.length() == 0) { + return editable; + } + + editorHeight = getHeight(); + + if (!newText && editorHeight > 0) { + firstLine = lineUtils.getFirstVisibleLine(verticalScroll, editorHeight, lineCount); + lastLine = lineUtils.getLastVisibleLine(verticalScroll, editorHeight, lineCount, deviceHeight); + firstVisibleIndex = getLayout().getLineStart(firstLine); + lastVisibleIndex = getLayout().getLineStart(lastLine); + } else { + firstVisibleIndex = 0; + lastVisibleIndex = CHARS_TO_COLOR; + } + + firstColoredIndex = firstVisibleIndex - (CHARS_TO_COLOR / 5); + + // normalize + if (firstColoredIndex < 0) + firstColoredIndex = 0; + if (lastVisibleIndex > editable.length()) + lastVisibleIndex = editable.length(); + if (firstColoredIndex > lastVisibleIndex) + firstColoredIndex = lastVisibleIndex; + + + textToHighlight = editable.subSequence(firstColoredIndex, lastVisibleIndex); + + if (fileExtension.contains("htm") + || fileExtension.contains("xml")) { + color(Patterns.HTML_OPEN_TAGS, editable, textToHighlight, firstColoredIndex); + color(Patterns.HTML_CLOSE_TAGS, editable, textToHighlight, firstColoredIndex); + color(Patterns.HTML_ATTRS, editable, textToHighlight, firstColoredIndex); + color(Patterns.GENERAL_STRINGS, editable, textToHighlight, firstColoredIndex); + color(Patterns.XML_COMMENTS, editable, textToHighlight, firstColoredIndex); + } else if (fileExtension.equals("css")) { + //color(CSS_STYLE_NAME, editable); + color(Patterns.CSS_ATTRS, editable, textToHighlight, firstColoredIndex); + color(Patterns.CSS_ATTR_VALUE, editable, textToHighlight, firstColoredIndex); + color(Patterns.SYMBOLS, editable, textToHighlight, firstColoredIndex); + color(Patterns.GENERAL_COMMENTS, editable, textToHighlight, firstColoredIndex); + } else if (Arrays.asList(MimeTypes.MIME_CODE).contains(fileExtension)) { + switch (fileExtension) { + case "lua": + color(Patterns.LUA_KEYWORDS, editable, textToHighlight, firstColoredIndex); + break; + case "py": + color(Patterns.PY_KEYWORDS, editable, textToHighlight, firstColoredIndex); + break; + default: + color(Patterns.GENERAL_KEYWORDS, editable, textToHighlight, firstColoredIndex); + break; + } + color(Patterns.NUMBERS_OR_SYMBOLS, editable, textToHighlight, firstColoredIndex); + color(Patterns.GENERAL_STRINGS, editable, textToHighlight, firstColoredIndex); + color(Patterns.GENERAL_COMMENTS, editable, textToHighlight, firstColoredIndex); + if (fileExtension.equals("php")) + color(Patterns.PHP_VARIABLES, editable, textToHighlight, firstColoredIndex); + } else if (Arrays.asList(MimeTypes.MIME_SQL).contains(fileExtension)) { + color(Patterns.SYMBOLS, editable, textToHighlight, firstColoredIndex); + color(Patterns.GENERAL_STRINGS, editable, textToHighlight, firstColoredIndex); + color(Patterns.SQL_KEYWORDS, editable, textToHighlight, firstColoredIndex); + } else { + if (!(Arrays.asList(MimeTypes.MIME_MARKDOWN).contains(fileExtension))) + color(Patterns.GENERAL_KEYWORDS, editable, textToHighlight, firstColoredIndex); + color(Patterns.NUMBERS_OR_SYMBOLS, editable, textToHighlight, firstColoredIndex); + color(Patterns.GENERAL_STRINGS, editable, textToHighlight, firstColoredIndex); + if (fileExtension.equals("prop") || fileExtension.contains("conf") || + (Arrays.asList(MimeTypes.MIME_MARKDOWN).contains(fileExtension))) + color(Patterns.GENERAL_COMMENTS_NO_SLASH, editable, textToHighlight, + firstColoredIndex); + else + color(Patterns.GENERAL_COMMENTS, editable, textToHighlight, firstColoredIndex); + + if ((Arrays.asList(MimeTypes.MIME_MARKDOWN).contains(fileExtension))) + color(Patterns.LINK, editable, textToHighlight, firstColoredIndex); + } + + return editable; + } + + public void enableTextChangedListener() { + if (!enabledChangeListener) { + addTextChangedListener(mChangeListener); + enabledChangeListener = true; + } + } + + public LineUtils getLineUtils() { + return lineUtils; + } + + private void color(Pattern pattern, + Editable allText, + CharSequence textToHighlight, + int start) { + int color = 0; + if (pattern.equals(Patterns.HTML_OPEN_TAGS) + || pattern.equals(Patterns.HTML_CLOSE_TAGS) + || pattern.equals(Patterns.GENERAL_KEYWORDS) + || pattern.equals(Patterns.SQL_KEYWORDS) + || pattern.equals(Patterns.PY_KEYWORDS) + || pattern.equals(Patterns.LUA_KEYWORDS) + + ) { + color = getResources().getColor(R.color.syntax_keyword); + } else if (pattern.equals(Patterns.HTML_ATTRS) + || pattern.equals(Patterns.CSS_ATTRS) + || pattern.equals(Patterns.LINK)) { + color = getResources().getColor(R.color.syntax_attr); + } else if (pattern.equals(Patterns.CSS_ATTR_VALUE)) { + color = getResources().getColor(R.color.syntax_attr_value); + } else if (pattern.equals(Patterns.XML_COMMENTS) + || pattern.equals(Patterns.GENERAL_COMMENTS) + || pattern.equals(Patterns.GENERAL_COMMENTS_NO_SLASH)) { + color = getResources().getColor(R.color.syntax_comment); + } else if (pattern.equals(Patterns.GENERAL_STRINGS)) { + color = getResources().getColor(R.color.syntax_string); + } else if (pattern.equals(Patterns.NUMBERS) || pattern.equals(Patterns.SYMBOLS) || pattern.equals(Patterns.NUMBERS_OR_SYMBOLS)) { + color = getResources().getColor(R.color.syntax_number); + } else if (pattern.equals(Patterns.PHP_VARIABLES)) { + color = getResources().getColor(R.color.syntax_variable); + } + + m = pattern.matcher(textToHighlight); + + while (m.find()) { + allText.setSpan( + new ForegroundColorSpan(color), + start + m.start(), + start + m.end(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + + /** + * Clear history. + */ + public void clearHistory() { + mEditHistory.clear(); + mShowUndo = getCanUndo(); + mShowRedo = getCanRedo(); + } + + /** + * Store preferences. + */ + public void storePersistentState( + SharedPreferences.Editor editor, + String prefix) { + // Store hash code of text in the editor so that we can check if the + // editor contents has changed. + editor.putString(prefix + ".hash", + String.valueOf( + getText().toString().hashCode())); + editor.putInt(prefix + ".maxSize", + mEditHistory.mmMaxHistorySize); + editor.putInt(prefix + ".position", + mEditHistory.mmPosition); + editor.putInt(prefix + ".size", + mEditHistory.mmHistory.size()); + + int i = 0; + for (EditItem ei : mEditHistory.mmHistory) { + String pre = prefix + "." + i; + + editor.putInt(pre + ".start", ei.mmStart); + editor.putString(pre + ".before", + ei.mmBefore.toString()); + editor.putString(pre + ".after", + ei.mmAfter.toString()); + + i++; + } + } + + /** + * Restore preferences. + * + * @param prefix The preference key prefix + * used when state was stored. + * @return did restore succeed? If this is + * false, the undo history will be empty. + */ + public boolean restorePersistentState( + SharedPreferences sp, String prefix) + throws IllegalStateException { + + boolean ok = + doRestorePersistentState(sp, prefix); + if (!ok) { + mEditHistory.clear(); + } + + return ok; + } + + private boolean doRestorePersistentState( + SharedPreferences sp, String prefix) { + + String hash = + sp.getString(prefix + ".hash", null); + if (hash == null) { + // No state to be restored. + return true; + } + + if (Integer.valueOf(hash) + != getText().toString().hashCode()) { + return false; + } + + mEditHistory.clear(); + mEditHistory.mmMaxHistorySize = + sp.getInt(prefix + ".maxSize", -1); + + int count = sp.getInt(prefix + ".size", -1); + if (count == -1) { + return false; + } + + for (int i = 0; i < count; i++) { + String pre = prefix + "." + i; + + int start = sp.getInt(pre + ".start", -1); + String before = + sp.getString(pre + ".before", null); + String after = + sp.getString(pre + ".after", null); + + if (start == -1 + || before == null + || after == null) { + return false; + } + mEditHistory.add( + new EditItem(start, before, after)); + } + + mEditHistory.mmPosition = + sp.getInt(prefix + ".position", -1); + return mEditHistory.mmPosition != -1; + + } + + /** + * Class that listens to changes in the text. + */ + private final class EditTextChangeListener + implements TextWatcher { + + /** + * The text that will be removed by the + * change event. + */ + private CharSequence mBeforeChange; + + /** + * The text that was inserted by the change + * event. + */ + private CharSequence mAfterChange; + + public void beforeTextChanged( + CharSequence s, int start, int count, + int after) { + if (mIsUndoOrRedo) { + return; + } + + mBeforeChange = + s.subSequence(start, start + count); + } + + public void onTextChanged(CharSequence s, + int start, int before, + int count) { + if (mIsUndoOrRedo) { + return; + } + + mAfterChange = + s.subSequence(start, start + count); + mEditHistory.add( + new EditItem(start, mBeforeChange, + mAfterChange)); + } + + public void afterTextChanged(Editable s) { + boolean showUndo = getCanUndo(); + boolean showRedo = getCanRedo(); + if (!canSaveFile) + canSaveFile = getCanUndo(); + if (showUndo != mShowUndo || showRedo != mShowRedo) { + mShowUndo = showUndo; + mShowRedo = showRedo; + ((MainActivity) getContext()).invalidateOptionsMenu(); + } + + ((MainActivity) getContext()).updateTextSyntax(); + } + } + + //endregion + + //region EDIT HISTORY + + /** + * Keeps track of all the edit history of a + * text. + */ + private final class EditHistory { + + /** + * The list of edits in chronological + * order. + */ + private final LinkedList + mmHistory = new LinkedList<>(); + /** + * The position from which an EditItem will + * be retrieved when getNext() is called. If + * getPrevious() has not been called, this + * has the same value as mmHistory.size(). + */ + private int mmPosition = 0; + /** + * Maximum undo history size. + */ + private int mmMaxHistorySize = -1; + + private int size() { + return mmHistory.size(); + } + + /** + * Clear history. + */ + private void clear() { + mmPosition = 0; + mmHistory.clear(); + } + + /** + * Adds a new edit operation to the history + * at the current position. If executed + * after a call to getPrevious() removes all + * the future history (elements with + * positions >= current history position). + */ + private void add(EditItem item) { + while (mmHistory.size() > mmPosition) { + mmHistory.removeLast(); + } + mmHistory.add(item); + mmPosition++; + + if (mmMaxHistorySize >= 0) { + trimHistory(); + } + } + + /** + * Trim history when it exceeds max history + * size. + */ + private void trimHistory() { + while (mmHistory.size() + > mmMaxHistorySize) { + mmHistory.removeFirst(); + mmPosition--; + } + + if (mmPosition < 0) { + mmPosition = 0; + } + } + + /** + * Set the maximum history size. If size is + * negative, then history size is only + * limited by the device memory. + */ + private void setMaxHistorySize( + int maxHistorySize) { + mmMaxHistorySize = maxHistorySize; + if (mmMaxHistorySize >= 0) { + trimHistory(); + } + } + + /** + * Traverses the history backward by one + * position, returns and item at that + * position. + */ + private EditItem getPrevious() { + if (mmPosition == 0) { + return null; + } + mmPosition--; + return mmHistory.get(mmPosition); + } + + /** + * Traverses the history forward by one + * position, returns and item at that + * position. + */ + private EditItem getNext() { + if (mmPosition >= mmHistory.size()) { + return null; + } + + EditItem item = mmHistory.get(mmPosition); + mmPosition++; + return item; + } + } + + /** + * Represents the changes performed by a + * single edit operation. + */ + private final class EditItem { + private final int mmStart; + private final CharSequence mmBefore; + private final CharSequence mmAfter; + + /** + * Constructs EditItem of a modification + * that was applied at position start and + * replaced CharSequence before with + * CharSequence after. + */ + public EditItem(int start, + CharSequence before, CharSequence after) { + mmStart = start; + mmBefore = before; + mmAfter = after; + } + } + //endregion + + + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/SelectFileActivity.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/SelectFileActivity.java index 3aeb5b5..f9679fe 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/SelectFileActivity.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/SelectFileActivity.java @@ -1,389 +1,389 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.activity; - -import android.content.Intent; -import android.os.AsyncTask; -import android.os.Bundle; -import android.support.v4.view.MenuItemCompat; -import android.support.v7.app.ActionBarActivity; -import android.support.v7.widget.SearchView; -import android.support.v7.widget.Toolbar; -import android.text.TextUtils; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.Filter; -import android.widget.ListView; -import android.widget.PopupMenu; -import android.widget.TextView; -import android.widget.Toast; - -import com.faizmalkani.floatingactionbutton.FloatingActionButton; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.sufficientlysecure.rootcommands.Shell; -import org.sufficientlysecure.rootcommands.Toolbox; - -import java.io.File; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.concurrent.TimeoutException; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.adapter.AdapterDetailedList; -import sharedcode.turboeditor.dialogfragment.EditTextDialog; -import sharedcode.turboeditor.preferences.PreferenceHelper; -import sharedcode.turboeditor.root.RootUtils; -import sharedcode.turboeditor.util.AlphanumComparator; -import sharedcode.turboeditor.util.Build; -import sharedcode.turboeditor.util.ThemeUtils; - -public class SelectFileActivity extends ActionBarActivity implements SearchView.OnQueryTextListener, AdapterView.OnItemClickListener, EditTextDialog.EditDialogListener { - private String currentFolder = PreferenceHelper.SD_CARD_ROOT; - private ListView listView; - private boolean wantAFile = true; - private MenuItem mSearchViewMenuItem; - private SearchView mSearchView; - private Filter filter; - - - @Override - protected void onCreate(Bundle savedInstanceState) { - - - ThemeUtils.setTheme(this); - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_select_file); - - Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar); - setSupportActionBar(toolbar); - - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - final Actions action = (Actions) getIntent().getExtras().getSerializable("action"); - wantAFile = action == Actions.SelectFile; - - listView = (ListView) findViewById(android.R.id.list); - listView.setOnItemClickListener(this); - listView.setTextFilterEnabled(true); - - FloatingActionButton mFab = (FloatingActionButton) findViewById(R.id.fabbutton); - mFab.setColor(getResources().getColor(R.color.fab_light)); - mFab.setDrawable(getResources().getDrawable(R.drawable.ic_fab_add)); - - mFab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - PopupMenu popup = new PopupMenu(SelectFileActivity.this, v); - - popup.getMenuInflater().inflate(R.menu.popup_new_file, popup.getMenu()); - - popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - int i = item.getItemId(); - if (i == R.id.im_new_file) { - EditTextDialog.newInstance(EditTextDialog.Actions.NewFile).show(getFragmentManager().beginTransaction(), "dialog"); - return true; - } else if (i == R.id.im_new_folder) { - EditTextDialog.newInstance(EditTextDialog.Actions.NewFolder).show(getFragmentManager().beginTransaction(), "dialog"); - return true; - } else { - return false; - } - } - }); - - popup.show(); - } - }); - - mFab.listenTo(listView); - - String lastNavigatedPath = PreferenceHelper.getWorkingFolder(this); - - File file = new File(lastNavigatedPath); - - if (!file.exists()) { - PreferenceHelper.setWorkingFolder(this, PreferenceHelper.SD_CARD_ROOT); - file = new File(PreferenceHelper.SD_CARD_ROOT); - } - - new UpdateList().execute(file.getAbsolutePath()); - } - - @Override - public void onBackPressed() { - if (currentFolder.isEmpty() || currentFolder.equals("/")) { - finish(); - } else { - File file = new File(currentFolder); - String parentFolder = file.getParent(); - new UpdateList().execute(parentFolder); - } - } - - public boolean onQueryTextChange(String newText) { - if (filter == null) - return true; - - if (TextUtils.isEmpty(newText)) { - filter.filter(null); - } else { - filter.filter(newText); - } - return true; - } - - public boolean onQueryTextSubmit(String query) { - return false; - } - - void returnData(String path) { - final Intent returnIntent = new Intent(); - returnIntent.putExtra("path", path); - setResult(RESULT_OK, returnIntent); - // finish the activity - finish(); - } - - - @Override - public void onItemClick(AdapterView parent, - View view, int position, long id) { - final String name = ((TextView) view.findViewById(android.R.id.text1)).getText().toString(); - if (name.equals("..")) { - if (currentFolder.equals("/")) { - new UpdateList().execute(PreferenceHelper.getWorkingFolder(this)); - } else { - File tempFile = new File(currentFolder); - if (tempFile.isFile()) { - tempFile = tempFile.getParentFile() - .getParentFile(); - } else { - tempFile = tempFile.getParentFile(); - } - new UpdateList().execute(tempFile.getAbsolutePath()); - } - return; - } else if (name.equals(getString(R.string.home))) { - new UpdateList().execute(PreferenceHelper.getWorkingFolder(this)); - return; - } - - final File selectedFile = new File(currentFolder, name); - - if (selectedFile.isFile() && wantAFile) { - returnData(selectedFile.getAbsolutePath()); - } else if (selectedFile.isDirectory()) { - new UpdateList().execute(selectedFile.getAbsolutePath()); - } - } - - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.activity_select_file, menu); - mSearchViewMenuItem = menu.findItem(R.id.im_search); - mSearchView = (SearchView) MenuItemCompat.getActionView(mSearchViewMenuItem); - mSearchView.setIconifiedByDefault(true); - mSearchView.setOnQueryTextListener(this); - mSearchView.setSubmitButtonEnabled(false); - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - // menu items - MenuItem imSetAsWorkingFolder = menu.findItem(R.id.im_set_as_working_folder); - MenuItem imIsWorkingFolder = menu.findItem(R.id.im_is_working_folder); - MenuItem imSelectFolder = menu.findItem(R.id.im_select_folder); - if (imSetAsWorkingFolder != null) { - // set the imSetAsWorkingFolder visible only if the two folder dont concide - imSetAsWorkingFolder.setVisible(!currentFolder.equals(PreferenceHelper.getWorkingFolder(SelectFileActivity.this))); - } - if (imIsWorkingFolder != null) { - // set visible is the other is invisible - imIsWorkingFolder.setVisible(!imSetAsWorkingFolder.isVisible()); - } - if (imSelectFolder != null) { - imSelectFolder.setVisible(!wantAFile); - } - return super.onPrepareOptionsMenu(menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int i = item.getItemId(); - if (i == android.R.id.home) { - finish(); - return true; - } else if (i == R.id.im_set_as_working_folder) { - PreferenceHelper.setWorkingFolder(SelectFileActivity.this, currentFolder); - invalidateOptionsMenu(); - return true; - } else if (i == R.id.im_is_working_folder) { - Toast.makeText(getBaseContext(), R.string.is_the_working_folder, Toast.LENGTH_SHORT).show(); - return true; - } else if (i == R.id.im_select_folder) { - returnData(currentFolder); - return true; - } - return super.onOptionsItemSelected(item); - } - - - @Override - public void onFinishEditDialog(final String inputText, final String hint, final EditTextDialog.Actions actions) { - if (actions == EditTextDialog.Actions.NewFile && !TextUtils.isEmpty(inputText)) { - File file = new File(currentFolder, inputText); - returnData(file.getAbsolutePath()); - } else if (actions == EditTextDialog.Actions.NewFolder && !TextUtils.isEmpty(inputText)) { - File file = new File(currentFolder, inputText); - file.mkdirs(); - new UpdateList().execute(currentFolder); - } - } - - public enum Actions { - SelectFile, SelectFolder - } - - private class UpdateList extends AsyncTask> { - - String exceptionMessage; - - @Override - protected void onPreExecute() { - super.onPreExecute(); - if (mSearchView != null) { - mSearchView.setIconified(true); - MenuItemCompat.collapseActionView(mSearchViewMenuItem); - mSearchView.setQuery("", false); - } - - } - - /** - * {@inheritDoc} - */ - @Override - protected LinkedList doInBackground(final String... params) { - try { - - final String path = params[0]; - if (TextUtils.isEmpty(path)) { - return null; - } - - File tempFile = new File(path); - if (tempFile.isFile()) { - tempFile = tempFile.getParentFile(); - } - - String[] unopenableExtensions = {"apk", "mp3", "mp4", "png", "jpg", "jpeg"}; - - final LinkedList fileDetails = new LinkedList<>(); - final LinkedList folderDetails = new LinkedList<>(); - final ArrayList files; - currentFolder = tempFile.getAbsolutePath(); - - boolean isRoot = false; - if (!tempFile.canRead()) { - try { - Shell shell = null; - shell = Shell.startRootShell(); - Toolbox tb = new Toolbox(shell); - isRoot = tb.isRootAccessGiven(); - } catch (IOException | TimeoutException e) { - e.printStackTrace(); - isRoot = false; - } - } - - files = RootUtils.getFileList(currentFolder, isRoot); - - Collections.sort(files, getFileNameComparator()); - - if (files != null) { - for (final File f : files) { - if (f.isDirectory()) { - folderDetails.add(new AdapterDetailedList.FileDetail(f.getName(), - getString(R.string.folder), - "")); - } else if (f.isFile() - && !FilenameUtils.isExtension(f.getName().toLowerCase(), unopenableExtensions) - && FileUtils.sizeOf(f) <= Build.MAX_FILE_SIZE * FileUtils.ONE_KB) { - final long fileSize = f.length(); - SimpleDateFormat format = new SimpleDateFormat("MMM dd, yyyy hh:mm a"); - String date = format.format(f.lastModified()); - fileDetails.add(new AdapterDetailedList.FileDetail(f.getName(), - FileUtils.byteCountToDisplaySize(fileSize), date)); - } - } - } - - folderDetails.addAll(fileDetails); - return folderDetails; - } catch (Exception e) { - exceptionMessage = e.getMessage(); - return null; - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void onPostExecute(final LinkedList names) { - if (names != null) { - boolean isRoot = currentFolder.equals("/"); - AdapterDetailedList mAdapter = new AdapterDetailedList(getBaseContext(), names, isRoot); - listView.setAdapter(mAdapter); - filter = mAdapter.getFilter(); - } - if (exceptionMessage != null) { - Toast.makeText(SelectFileActivity.this, exceptionMessage, Toast.LENGTH_SHORT).show(); - } - invalidateOptionsMenu(); - super.onPostExecute(names); - } - - public final Comparator getFileNameComparator() { - return new AlphanumComparator() { - /** - * {@inheritDoc} - */ - @Override - public String getTheString(Object obj) { - return ((File) obj).getName() - .toLowerCase(); - } - }; - } - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.activity; + +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.view.MenuItemCompat; +import android.support.v7.app.ActionBarActivity; +import android.support.v7.widget.SearchView; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Filter; +import android.widget.ListView; +import android.widget.PopupMenu; +import android.widget.TextView; +import android.widget.Toast; + +import com.faizmalkani.floatingactionbutton.FloatingActionButton; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.sufficientlysecure.rootcommands.Shell; +import org.sufficientlysecure.rootcommands.Toolbox; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.concurrent.TimeoutException; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.adapter.AdapterDetailedList; +import sharedcode.turboeditor.dialogfragment.EditTextDialog; +import sharedcode.turboeditor.preferences.PreferenceHelper; +import sharedcode.turboeditor.root.RootUtils; +import sharedcode.turboeditor.util.AlphanumComparator; +import sharedcode.turboeditor.util.Build; +import sharedcode.turboeditor.util.ThemeUtils; + +public class SelectFileActivity extends ActionBarActivity implements SearchView.OnQueryTextListener, AdapterView.OnItemClickListener, EditTextDialog.EditDialogListener { + private String currentFolder = PreferenceHelper.SD_CARD_ROOT; + private ListView listView; + private boolean wantAFile = true; + private MenuItem mSearchViewMenuItem; + private SearchView mSearchView; + private Filter filter; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + + + ThemeUtils.setTheme(this); + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_select_file); + + Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar); + setSupportActionBar(toolbar); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + final Actions action = (Actions) getIntent().getExtras().getSerializable("action"); + wantAFile = action == Actions.SelectFile; + + listView = (ListView) findViewById(android.R.id.list); + listView.setOnItemClickListener(this); + listView.setTextFilterEnabled(true); + + FloatingActionButton mFab = (FloatingActionButton) findViewById(R.id.fabbutton); + mFab.setColor(getResources().getColor(R.color.fab_light)); + mFab.setDrawable(getResources().getDrawable(R.drawable.ic_fab_add)); + + mFab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + PopupMenu popup = new PopupMenu(SelectFileActivity.this, v); + + popup.getMenuInflater().inflate(R.menu.popup_new_file, popup.getMenu()); + + popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + int i = item.getItemId(); + if (i == R.id.im_new_file) { + EditTextDialog.newInstance(EditTextDialog.Actions.NewFile).show(getFragmentManager().beginTransaction(), "dialog"); + return true; + } else if (i == R.id.im_new_folder) { + EditTextDialog.newInstance(EditTextDialog.Actions.NewFolder).show(getFragmentManager().beginTransaction(), "dialog"); + return true; + } else { + return false; + } + } + }); + + popup.show(); + } + }); + + mFab.listenTo(listView); + + String lastNavigatedPath = PreferenceHelper.getWorkingFolder(this); + + File file = new File(lastNavigatedPath); + + if (!file.exists()) { + PreferenceHelper.setWorkingFolder(this, PreferenceHelper.SD_CARD_ROOT); + file = new File(PreferenceHelper.SD_CARD_ROOT); + } + + new UpdateList().execute(file.getAbsolutePath()); + } + + @Override + public void onBackPressed() { + if (currentFolder.isEmpty() || currentFolder.equals("/")) { + finish(); + } else { + File file = new File(currentFolder); + String parentFolder = file.getParent(); + new UpdateList().execute(parentFolder); + } + } + + public boolean onQueryTextChange(String newText) { + if (filter == null) + return true; + + if (TextUtils.isEmpty(newText)) { + filter.filter(null); + } else { + filter.filter(newText); + } + return true; + } + + public boolean onQueryTextSubmit(String query) { + return false; + } + + void returnData(String path) { + final Intent returnIntent = new Intent(); + returnIntent.putExtra("path", path); + setResult(RESULT_OK, returnIntent); + // finish the activity + finish(); + } + + + @Override + public void onItemClick(AdapterView parent, + View view, int position, long id) { + final String name = ((TextView) view.findViewById(android.R.id.text1)).getText().toString(); + if (name.equals("..")) { + if (currentFolder.equals("/")) { + new UpdateList().execute(PreferenceHelper.getWorkingFolder(this)); + } else { + File tempFile = new File(currentFolder); + if (tempFile.isFile()) { + tempFile = tempFile.getParentFile() + .getParentFile(); + } else { + tempFile = tempFile.getParentFile(); + } + new UpdateList().execute(tempFile.getAbsolutePath()); + } + return; + } else if (name.equals(getString(R.string.home))) { + new UpdateList().execute(PreferenceHelper.getWorkingFolder(this)); + return; + } + + final File selectedFile = new File(currentFolder, name); + + if (selectedFile.isFile() && wantAFile) { + returnData(selectedFile.getAbsolutePath()); + } else if (selectedFile.isDirectory()) { + new UpdateList().execute(selectedFile.getAbsolutePath()); + } + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.activity_select_file, menu); + mSearchViewMenuItem = menu.findItem(R.id.im_search); + mSearchView = (SearchView) MenuItemCompat.getActionView(mSearchViewMenuItem); + mSearchView.setIconifiedByDefault(true); + mSearchView.setOnQueryTextListener(this); + mSearchView.setSubmitButtonEnabled(false); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + // menu items + MenuItem imSetAsWorkingFolder = menu.findItem(R.id.im_set_as_working_folder); + MenuItem imIsWorkingFolder = menu.findItem(R.id.im_is_working_folder); + MenuItem imSelectFolder = menu.findItem(R.id.im_select_folder); + if (imSetAsWorkingFolder != null) { + // set the imSetAsWorkingFolder visible only if the two folder dont concide + imSetAsWorkingFolder.setVisible(!currentFolder.equals(PreferenceHelper.getWorkingFolder(SelectFileActivity.this))); + } + if (imIsWorkingFolder != null) { + // set visible is the other is invisible + imIsWorkingFolder.setVisible(!imSetAsWorkingFolder.isVisible()); + } + if (imSelectFolder != null) { + imSelectFolder.setVisible(!wantAFile); + } + return super.onPrepareOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int i = item.getItemId(); + if (i == android.R.id.home) { + finish(); + return true; + } else if (i == R.id.im_set_as_working_folder) { + PreferenceHelper.setWorkingFolder(SelectFileActivity.this, currentFolder); + invalidateOptionsMenu(); + return true; + } else if (i == R.id.im_is_working_folder) { + Toast.makeText(getBaseContext(), R.string.is_the_working_folder, Toast.LENGTH_SHORT).show(); + return true; + } else if (i == R.id.im_select_folder) { + returnData(currentFolder); + return true; + } + return super.onOptionsItemSelected(item); + } + + + @Override + public void onFinishEditDialog(final String inputText, final String hint, final EditTextDialog.Actions actions) { + if (actions == EditTextDialog.Actions.NewFile && !TextUtils.isEmpty(inputText)) { + File file = new File(currentFolder, inputText); + returnData(file.getAbsolutePath()); + } else if (actions == EditTextDialog.Actions.NewFolder && !TextUtils.isEmpty(inputText)) { + File file = new File(currentFolder, inputText); + file.mkdirs(); + new UpdateList().execute(currentFolder); + } + } + + public enum Actions { + SelectFile, SelectFolder + } + + private class UpdateList extends AsyncTask> { + + String exceptionMessage; + + @Override + protected void onPreExecute() { + super.onPreExecute(); + if (mSearchView != null) { + mSearchView.setIconified(true); + MenuItemCompat.collapseActionView(mSearchViewMenuItem); + mSearchView.setQuery("", false); + } + + } + + /** + * {@inheritDoc} + */ + @Override + protected LinkedList doInBackground(final String... params) { + try { + + final String path = params[0]; + if (TextUtils.isEmpty(path)) { + return null; + } + + File tempFile = new File(path); + if (tempFile.isFile()) { + tempFile = tempFile.getParentFile(); + } + + String[] unopenableExtensions = {"apk", "mp3", "mp4", "png", "jpg", "jpeg"}; + + final LinkedList fileDetails = new LinkedList<>(); + final LinkedList folderDetails = new LinkedList<>(); + final ArrayList files; + currentFolder = tempFile.getAbsolutePath(); + + boolean isRoot = false; + if (!tempFile.canRead()) { + try { + Shell shell = null; + shell = Shell.startRootShell(); + Toolbox tb = new Toolbox(shell); + isRoot = tb.isRootAccessGiven(); + } catch (IOException | TimeoutException e) { + e.printStackTrace(); + isRoot = false; + } + } + + files = RootUtils.getFileList(currentFolder, isRoot); + + Collections.sort(files, getFileNameComparator()); + + if (files != null) { + for (final File f : files) { + if (f.isDirectory()) { + folderDetails.add(new AdapterDetailedList.FileDetail(f.getName(), + getString(R.string.folder), + "")); + } else if (f.isFile() + && !FilenameUtils.isExtension(f.getName().toLowerCase(), unopenableExtensions) + && FileUtils.sizeOf(f) <= Build.MAX_FILE_SIZE * FileUtils.ONE_KB) { + final long fileSize = f.length(); + SimpleDateFormat format = new SimpleDateFormat("MMM dd, yyyy hh:mm a"); + String date = format.format(f.lastModified()); + fileDetails.add(new AdapterDetailedList.FileDetail(f.getName(), + FileUtils.byteCountToDisplaySize(fileSize), date)); + } + } + } + + folderDetails.addAll(fileDetails); + return folderDetails; + } catch (Exception e) { + exceptionMessage = e.getMessage(); + return null; + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void onPostExecute(final LinkedList names) { + if (names != null) { + boolean isRoot = currentFolder.equals("/"); + AdapterDetailedList mAdapter = new AdapterDetailedList(getBaseContext(), names, isRoot); + listView.setAdapter(mAdapter); + filter = mAdapter.getFilter(); + } + if (exceptionMessage != null) { + Toast.makeText(SelectFileActivity.this, exceptionMessage, Toast.LENGTH_SHORT).show(); + } + invalidateOptionsMenu(); + super.onPostExecute(names); + } + + public final Comparator getFileNameComparator() { + return new AlphanumComparator() { + /** + * {@inheritDoc} + */ + @Override + public String getTheString(Object obj) { + return ((File) obj).getName() + .toLowerCase(); + } + }; + } + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterDetailedList.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterDetailedList.java index 0b44d7f..dfe867b 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterDetailedList.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterDetailedList.java @@ -1,204 +1,204 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.adapter; - -import android.content.Context; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.Filter; -import android.widget.ImageView; -import android.widget.TextView; - -import org.apache.commons.io.FilenameUtils; - -import java.util.Arrays; -import java.util.LinkedList; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.util.MimeTypes; - -public class AdapterDetailedList extends - ArrayAdapter { - - // Layout Inflater - private final LayoutInflater inflater; - private final LinkedList orig; - private CustomFilter customFilter; - // List of file details - private LinkedList fileDetails; - - public AdapterDetailedList(final Context context, - final LinkedList fileDetails, - final boolean isRoot) { - super(context, R.layout.item_file_list, fileDetails); - this.fileDetails = fileDetails; - this.orig = fileDetails; - this.inflater = LayoutInflater.from(context); - if (!isRoot) { - this.fileDetails.addFirst(new FileDetail("..", context.getString(R.string.folder), "")); - } else { - this.fileDetails.addFirst(new FileDetail(context.getString(R.string.home), context.getString(R.string.folder), "")); - } - } - - - @Override - public View getView(final int position, - View convertView, final ViewGroup parent) { - if (convertView == null) { - convertView = this.inflater - .inflate(R.layout.item_file_list, - null); - final ViewHolder hold = new ViewHolder(); - hold.nameLabel = (TextView) convertView.findViewById(android.R.id.text1); - hold.detailLabel = (TextView) convertView.findViewById(android.R.id.text2); - hold.icon = (ImageView) convertView.findViewById(android.R.id.icon); - convertView.setTag(hold); - final FileDetail fileDetail = fileDetails.get(position); - final String fileName = fileDetail.getName(); - setIcon(hold, fileDetail); - hold.nameLabel.setText(fileName); - hold.detailLabel.setText(fileDetail.getSize() + "\t\t" + fileDetail.getDateModified()); - } else { - final ViewHolder hold = ((ViewHolder) convertView.getTag()); - final FileDetail fileDetail = fileDetails.get(position); - final String fileName = fileDetail.getName(); - setIcon(hold, fileDetail); - hold.nameLabel.setText(fileName); - hold.detailLabel.setText(fileDetail.getSize() + "\t\t" + fileDetail.getDateModified()); - } - return convertView; - } - - @Override - public int getCount() { - return fileDetails.size(); - } - - private void setIcon(final ViewHolder viewHolder, final FileDetail fileDetail) { - final String fileName = fileDetail.getName(); - final String ext = FilenameUtils.getExtension(fileName); - if (fileDetail.isFolder()) { - viewHolder.icon.setImageResource(R.color.file_folder); - } else if (Arrays.asList(MimeTypes.MIME_HTML).contains(ext) || ext.endsWith("html")) { - viewHolder.icon.setImageResource(R.color.file_html); - } else if (Arrays.asList(MimeTypes.MIME_CODE).contains(ext) - || fileName.endsWith("css") - || fileName.endsWith("js")) { - viewHolder.icon.setImageResource(R.color.file_code); - } else if (Arrays.asList(MimeTypes.MIME_ARCHIVE).contains(ext)) { - viewHolder.icon.setImageResource(R.color.file_archive); - } else if (Arrays.asList(MimeTypes.MIME_MUSIC) - .contains(ext)) { - viewHolder.icon.setImageResource(R.color.file_media_music); - } else if (Arrays.asList(MimeTypes.MIME_PICTURE).contains(ext)) { - viewHolder.icon.setImageResource(R.color.file_media_picture); - } else if (Arrays.asList(MimeTypes.MIME_VIDEO).contains(ext)) { - viewHolder.icon.setImageResource(R.color.file_media_video); - } else { - viewHolder.icon.setImageResource(R.color.file_text); - } - } - - @Override - public Filter getFilter() { - if (customFilter == null) { - customFilter = new CustomFilter(); - } - return customFilter; - } - - public static class ViewHolder { - - // Name of the file - public TextView nameLabel; - - // Size of the file - public TextView detailLabel; - - // Icon of the file - public ImageView icon; - } - - public static class FileDetail { - private final String name; - private final String size; - private final String dateModified; - private final boolean isFolder; - - public FileDetail(String name, String size, - String dateModified) { - this.name = name; - this.size = size; - this.dateModified = dateModified; - isFolder = TextUtils.isEmpty(dateModified); - } - - public String getDateModified() { - return dateModified; - } - - public String getSize() { - return size; - } - - public String getName() { - return name; - } - - public boolean isFolder() { - return isFolder; - } - } - - private class CustomFilter extends Filter { - - @Override - protected FilterResults performFiltering(CharSequence constraint) { - FilterResults results = new FilterResults(); - if (constraint == null || constraint.length() == 0) { - results.values = orig; - results.count = orig.size(); - } else { - LinkedList nHolderList = new LinkedList<>(); - for (FileDetail h : orig) { - if (h.getName().toLowerCase().contains(constraint.toString().toLowerCase())) - nHolderList.add(h); - } - results.values = nHolderList; - results.count = nHolderList.size(); - } - return results; - } - - @SuppressWarnings("unchecked") - @Override - protected void publishResults(CharSequence constraint, - FilterResults results) { - - - fileDetails = (LinkedList) results.values; - notifyDataSetChanged(); - } - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.adapter; + +import android.content.Context; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Filter; +import android.widget.ImageView; +import android.widget.TextView; + +import org.apache.commons.io.FilenameUtils; + +import java.util.Arrays; +import java.util.LinkedList; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.util.MimeTypes; + +public class AdapterDetailedList extends + ArrayAdapter { + + // Layout Inflater + private final LayoutInflater inflater; + private final LinkedList orig; + private CustomFilter customFilter; + // List of file details + private LinkedList fileDetails; + + public AdapterDetailedList(final Context context, + final LinkedList fileDetails, + final boolean isRoot) { + super(context, R.layout.item_file_list, fileDetails); + this.fileDetails = fileDetails; + this.orig = fileDetails; + this.inflater = LayoutInflater.from(context); + if (!isRoot) { + this.fileDetails.addFirst(new FileDetail("..", context.getString(R.string.folder), "")); + } else { + this.fileDetails.addFirst(new FileDetail(context.getString(R.string.home), context.getString(R.string.folder), "")); + } + } + + + @Override + public View getView(final int position, + View convertView, final ViewGroup parent) { + if (convertView == null) { + convertView = this.inflater + .inflate(R.layout.item_file_list, + null); + final ViewHolder hold = new ViewHolder(); + hold.nameLabel = (TextView) convertView.findViewById(android.R.id.text1); + hold.detailLabel = (TextView) convertView.findViewById(android.R.id.text2); + hold.icon = (ImageView) convertView.findViewById(android.R.id.icon); + convertView.setTag(hold); + final FileDetail fileDetail = fileDetails.get(position); + final String fileName = fileDetail.getName(); + setIcon(hold, fileDetail); + hold.nameLabel.setText(fileName); + hold.detailLabel.setText(fileDetail.getSize() + "\t\t" + fileDetail.getDateModified()); + } else { + final ViewHolder hold = ((ViewHolder) convertView.getTag()); + final FileDetail fileDetail = fileDetails.get(position); + final String fileName = fileDetail.getName(); + setIcon(hold, fileDetail); + hold.nameLabel.setText(fileName); + hold.detailLabel.setText(fileDetail.getSize() + "\t\t" + fileDetail.getDateModified()); + } + return convertView; + } + + @Override + public int getCount() { + return fileDetails.size(); + } + + private void setIcon(final ViewHolder viewHolder, final FileDetail fileDetail) { + final String fileName = fileDetail.getName(); + final String ext = FilenameUtils.getExtension(fileName); + if (fileDetail.isFolder()) { + viewHolder.icon.setImageResource(R.color.file_folder); + } else if (Arrays.asList(MimeTypes.MIME_HTML).contains(ext) || ext.endsWith("html")) { + viewHolder.icon.setImageResource(R.color.file_html); + } else if (Arrays.asList(MimeTypes.MIME_CODE).contains(ext) + || fileName.endsWith("css") + || fileName.endsWith("js")) { + viewHolder.icon.setImageResource(R.color.file_code); + } else if (Arrays.asList(MimeTypes.MIME_ARCHIVE).contains(ext)) { + viewHolder.icon.setImageResource(R.color.file_archive); + } else if (Arrays.asList(MimeTypes.MIME_MUSIC) + .contains(ext)) { + viewHolder.icon.setImageResource(R.color.file_media_music); + } else if (Arrays.asList(MimeTypes.MIME_PICTURE).contains(ext)) { + viewHolder.icon.setImageResource(R.color.file_media_picture); + } else if (Arrays.asList(MimeTypes.MIME_VIDEO).contains(ext)) { + viewHolder.icon.setImageResource(R.color.file_media_video); + } else { + viewHolder.icon.setImageResource(R.color.file_text); + } + } + + @Override + public Filter getFilter() { + if (customFilter == null) { + customFilter = new CustomFilter(); + } + return customFilter; + } + + public static class ViewHolder { + + // Name of the file + public TextView nameLabel; + + // Size of the file + public TextView detailLabel; + + // Icon of the file + public ImageView icon; + } + + public static class FileDetail { + private final String name; + private final String size; + private final String dateModified; + private final boolean isFolder; + + public FileDetail(String name, String size, + String dateModified) { + this.name = name; + this.size = size; + this.dateModified = dateModified; + isFolder = TextUtils.isEmpty(dateModified); + } + + public String getDateModified() { + return dateModified; + } + + public String getSize() { + return size; + } + + public String getName() { + return name; + } + + public boolean isFolder() { + return isFolder; + } + } + + private class CustomFilter extends Filter { + + @Override + protected FilterResults performFiltering(CharSequence constraint) { + FilterResults results = new FilterResults(); + if (constraint == null || constraint.length() == 0) { + results.values = orig; + results.count = orig.size(); + } else { + LinkedList nHolderList = new LinkedList<>(); + for (FileDetail h : orig) { + if (h.getName().toLowerCase().contains(constraint.toString().toLowerCase())) + nHolderList.add(h); + } + results.values = nHolderList; + results.count = nHolderList.size(); + } + return results; + } + + @SuppressWarnings("unchecked") + @Override + protected void publishResults(CharSequence constraint, + FilterResults results) { + + + fileDetails = (LinkedList) results.values; + notifyDataSetChanged(); + } + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterDrawer.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterDrawer.java index a076be7..7851294 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterDrawer.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterDrawer.java @@ -1,130 +1,130 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.adapter; - -import android.content.Context; -import android.graphics.Typeface; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.TextView; - -import java.io.File; -import java.util.List; - -import sharedcode.turboeditor.R; - -public class AdapterDrawer extends - ArrayAdapter { - - private final Callbacks callbacks; - // Layout Inflater - private final LayoutInflater inflater; - // List of file details - private final List files; - private String selectedPath = ""; - - public AdapterDrawer(Context context, - List files, - Callbacks callbacks) { - super(context, R.layout.item_file_list, files); - this.files = files; - this.inflater = LayoutInflater.from(context); - this.callbacks = callbacks; - } - - - @Override - public View getView(final int position, - View convertView, final ViewGroup parent) { - if (convertView == null) { - convertView = this.inflater - .inflate(R.layout.item_drawer_list, - parent, false); - final ViewHolder hold = new ViewHolder(); - hold.nameLabel = (TextView) convertView.findViewById(android.R.id.text1); - hold.cancelButton = (ImageView) convertView.findViewById(R.id.button_remove_from_list); - convertView.setTag(hold); - - final String fileName = files.get(position).getName(); - hold.nameLabel.setText(fileName); - hold.cancelButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - boolean closeOpenedFile = TextUtils.equals(selectedPath, files.get(position).getAbsolutePath()); - callbacks.CancelItem(position, closeOpenedFile); - if (closeOpenedFile) - selectedPath = ""; - - } - }); - - if (TextUtils.equals(selectedPath, files.get(position).getAbsolutePath())) { - hold.nameLabel.setTypeface(null, Typeface.BOLD); - } else { - hold.nameLabel.setTypeface(null, Typeface.NORMAL); - } - - } else { - final ViewHolder hold = ((ViewHolder) convertView.getTag()); - final String fileName = files.get(position).getName(); - hold.nameLabel.setText(fileName); - hold.cancelButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - boolean closeOpenedFile = TextUtils.equals(selectedPath, files.get(position).getAbsolutePath()); - callbacks.CancelItem(position, closeOpenedFile); - if (closeOpenedFile) - selectedPath = ""; - } - }); - - if (TextUtils.equals(selectedPath, files.get(position).getAbsolutePath())) { - hold.nameLabel.setTypeface(null, Typeface.BOLD); - } else { - hold.nameLabel.setTypeface(null, Typeface.NORMAL); - } - } - return convertView; - } - - public void selectView(String selectedPath) { - //callbacks.ItemSelected(selectedPath); - this.selectedPath = selectedPath; - notifyDataSetChanged(); - } - - public interface Callbacks { - void CancelItem(int position, boolean andCloseOpenedFile); - - //void ItemSelected(String path); - } - - public static class ViewHolder { - - // Name of the file - public TextView nameLabel; - - public ImageView cancelButton; - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.adapter; + +import android.content.Context; +import android.graphics.Typeface; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import java.io.File; +import java.util.List; + +import sharedcode.turboeditor.R; + +public class AdapterDrawer extends + ArrayAdapter { + + private final Callbacks callbacks; + // Layout Inflater + private final LayoutInflater inflater; + // List of file details + private final List files; + private String selectedPath = ""; + + public AdapterDrawer(Context context, + List files, + Callbacks callbacks) { + super(context, R.layout.item_file_list, files); + this.files = files; + this.inflater = LayoutInflater.from(context); + this.callbacks = callbacks; + } + + + @Override + public View getView(final int position, + View convertView, final ViewGroup parent) { + if (convertView == null) { + convertView = this.inflater + .inflate(R.layout.item_drawer_list, + parent, false); + final ViewHolder hold = new ViewHolder(); + hold.nameLabel = (TextView) convertView.findViewById(android.R.id.text1); + hold.cancelButton = (ImageView) convertView.findViewById(R.id.button_remove_from_list); + convertView.setTag(hold); + + final String fileName = files.get(position).getName(); + hold.nameLabel.setText(fileName); + hold.cancelButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean closeOpenedFile = TextUtils.equals(selectedPath, files.get(position).getAbsolutePath()); + callbacks.CancelItem(position, closeOpenedFile); + if (closeOpenedFile) + selectedPath = ""; + + } + }); + + if (TextUtils.equals(selectedPath, files.get(position).getAbsolutePath())) { + hold.nameLabel.setTypeface(null, Typeface.BOLD); + } else { + hold.nameLabel.setTypeface(null, Typeface.NORMAL); + } + + } else { + final ViewHolder hold = ((ViewHolder) convertView.getTag()); + final String fileName = files.get(position).getName(); + hold.nameLabel.setText(fileName); + hold.cancelButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean closeOpenedFile = TextUtils.equals(selectedPath, files.get(position).getAbsolutePath()); + callbacks.CancelItem(position, closeOpenedFile); + if (closeOpenedFile) + selectedPath = ""; + } + }); + + if (TextUtils.equals(selectedPath, files.get(position).getAbsolutePath())) { + hold.nameLabel.setTypeface(null, Typeface.BOLD); + } else { + hold.nameLabel.setTypeface(null, Typeface.NORMAL); + } + } + return convertView; + } + + public void selectView(String selectedPath) { + //callbacks.ItemSelected(selectedPath); + this.selectedPath = selectedPath; + notifyDataSetChanged(); + } + + public interface Callbacks { + void CancelItem(int position, boolean andCloseOpenedFile); + + //void ItemSelected(String path); + } + + public static class ViewHolder { + + // Name of the file + public TextView nameLabel; + + public ImageView cancelButton; + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterTwoItem.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterTwoItem.java index bb2782c..b666854 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterTwoItem.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/adapter/AdapterTwoItem.java @@ -1,75 +1,75 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.adapter; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import sharedcode.turboeditor.R; - -public class AdapterTwoItem extends - ArrayAdapter { - - private final LayoutInflater inflater; - private final String[] lines1; - private final String[] lines2; - - public AdapterTwoItem(Context context, - String[] lines1, - String[] lines2) { - super(context, R.layout.item_two_lines, lines1); - this.lines1 = lines1; - this.lines2 = lines2; - this.inflater = LayoutInflater.from(context); - } - - - @Override - public View getView(final int position, - View convertView, final ViewGroup parent) { - if (convertView == null) { - convertView = this.inflater - .inflate(R.layout.item_two_lines, - parent, false); - final ViewHolder hold = new ViewHolder(); - hold.line1 = (TextView) convertView.findViewById(android.R.id.text1); - hold.line2 = (TextView) convertView.findViewById(android.R.id.text2); - convertView.setTag(hold); - - hold.line1.setText(lines1[position]); - hold.line2.setText(lines2[position]); - } else { - final ViewHolder hold = ((ViewHolder) convertView.getTag()); - hold.line1.setText(lines1[position]); - hold.line2.setText(lines2[position]); - } - return convertView; - } - - public static class ViewHolder { - - public TextView line1; - public TextView line2; - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import sharedcode.turboeditor.R; + +public class AdapterTwoItem extends + ArrayAdapter { + + private final LayoutInflater inflater; + private final String[] lines1; + private final String[] lines2; + + public AdapterTwoItem(Context context, + String[] lines1, + String[] lines2) { + super(context, R.layout.item_two_lines, lines1); + this.lines1 = lines1; + this.lines2 = lines2; + this.inflater = LayoutInflater.from(context); + } + + + @Override + public View getView(final int position, + View convertView, final ViewGroup parent) { + if (convertView == null) { + convertView = this.inflater + .inflate(R.layout.item_two_lines, + parent, false); + final ViewHolder hold = new ViewHolder(); + hold.line1 = (TextView) convertView.findViewById(android.R.id.text1); + hold.line2 = (TextView) convertView.findViewById(android.R.id.text2); + convertView.setTag(hold); + + hold.line1.setText(lines1[position]); + hold.line2.setText(lines2[position]); + } else { + final ViewHolder hold = ((ViewHolder) convertView.getTag()); + hold.line1.setText(lines1[position]); + hold.line2.setText(lines2[position]); + } + return convertView; + } + + public static class ViewHolder { + + public TextView line1; + public TextView line2; + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/application/MyApp.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/application/MyApp.java index 1c84e71..db3a1c0 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/application/MyApp.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/application/MyApp.java @@ -1,44 +1,44 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.application; - -import android.app.Application; -import android.view.ViewConfiguration; - -import java.lang.reflect.Field; - -public class MyApp extends Application { - - @Override - public void onCreate() { - super.onCreate(); - // force to sow the overflow menu icon - try { - ViewConfiguration config = ViewConfiguration.get(this); - Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); - if (menuKeyField != null) { - menuKeyField.setAccessible(true); - menuKeyField.setBoolean(config, false); - } - } catch (Exception ex) { - // Ignore - } - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.application; + +import android.app.Application; +import android.view.ViewConfiguration; + +import java.lang.reflect.Field; + +public class MyApp extends Application { + + @Override + public void onCreate() { + super.onCreate(); + // force to sow the overflow menu icon + try { + ViewConfiguration config = ViewConfiguration.get(this); + Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); + if (menuKeyField != null) { + menuKeyField.setAccessible(true); + menuKeyField.setBoolean(config, false); + } + } catch (Exception ex) { + // Ignore + } + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/ChangelogDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/ChangelogDialog.java index 2d2818a..c2a70ef 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/ChangelogDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/ChangelogDialog.java @@ -1,91 +1,91 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.dialogfragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.app.Fragment; -import android.app.FragmentManager; -import android.app.FragmentTransaction; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.LayoutInflater; - -import it.gmariotti.changelibs.library.view.ChangeLogListView; -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.util.Build; - -public class ChangelogDialog extends DialogFragment { - - public static void showChangeLogDialog(FragmentManager fragmentManager) { - ChangelogDialog changelogDialog = new ChangelogDialog(); - FragmentTransaction ft = fragmentManager.beginTransaction(); - Fragment prev = fragmentManager.findFragmentByTag("changelogdemo_dialog"); - if (prev != null) { - ft.remove(prev); - } - ft.addToBackStack(null); - changelogDialog.show(ft, "changelogdemo_dialog"); - } - - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - LayoutInflater layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - ChangeLogListView chgList = (ChangeLogListView) layoutInflater.inflate(R.layout.demo_changelog_fragment_dialogstandard, null); - - return new AlertDialog.Builder(getActivity()) - .setTitle(R.string.changelog) - .setView(chgList) - .setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - dialog.dismiss(); - } - } - ) - .setPositiveButton(R.string.vota, new DialogInterface.OnClickListener() { - /** - * {@inheritDoc} - */ - @Override - public void onClick(final DialogInterface dialog, final int which) { - try { - if (Build.FOR_AMAZON) { - String url = "amzn://apps/android?p=com.maskyn.fileeditor"; - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); - } else { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.maskyn.fileeditor")) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); - } - } catch (Exception e) { - } - } - }) - .create(); - - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.dialogfragment; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.LayoutInflater; + +import it.gmariotti.changelibs.library.view.ChangeLogListView; +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.util.Build; + +public class ChangelogDialog extends DialogFragment { + + public static void showChangeLogDialog(FragmentManager fragmentManager) { + ChangelogDialog changelogDialog = new ChangelogDialog(); + FragmentTransaction ft = fragmentManager.beginTransaction(); + Fragment prev = fragmentManager.findFragmentByTag("changelogdemo_dialog"); + if (prev != null) { + ft.remove(prev); + } + ft.addToBackStack(null); + changelogDialog.show(ft, "changelogdemo_dialog"); + } + + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + LayoutInflater layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + ChangeLogListView chgList = (ChangeLogListView) layoutInflater.inflate(R.layout.demo_changelog_fragment_dialogstandard, null); + + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.changelog) + .setView(chgList) + .setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + dialog.dismiss(); + } + } + ) + .setPositiveButton(R.string.vota, new DialogInterface.OnClickListener() { + /** + * {@inheritDoc} + */ + @Override + public void onClick(final DialogInterface dialog, final int which) { + try { + if (Build.FOR_AMAZON) { + String url = "amzn://apps/android?p=com.maskyn.fileeditor"; + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } else { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.maskyn.fileeditor")) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + } catch (Exception e) { + } + } + }) + .create(); + + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EditTextDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EditTextDialog.java index 50a2a8d..183a6ae 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EditTextDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EditTextDialog.java @@ -1,132 +1,132 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.dialogfragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.View; -import android.view.WindowManager; -import android.view.inputmethod.EditorInfo; -import android.widget.EditText; -import android.widget.TextView; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.views.DialogHelper; - -// ... -public class EditTextDialog extends DialogFragment implements TextView.OnEditorActionListener { - - private EditText mEditText; - - public static EditTextDialog newInstance(final Actions action) { - return EditTextDialog.newInstance(action, ""); - } - - public static EditTextDialog newInstance(final Actions action, final String hint) { - final EditTextDialog f = new EditTextDialog(); - final Bundle args = new Bundle(); - args.putSerializable("action", action); - args.putString("hint", hint); - f.setArguments(args); - return f; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - final Actions action = (Actions) getArguments().getSerializable("action"); - final String title; - switch (action) { - case NewFile: - title = getString(R.string.file); - break; - case NewFolder: - title = getString(R.string.folder); - break; - default: - title = null; - break; - } - - View view = new DialogHelper.Builder(getActivity()) - .setTitle(title) - .setView(R.layout.dialog_fragment_edittext) - .createSkeletonView(); - this.mEditText = (EditText) view.findViewById(android.R.id.edit); - this.mEditText.setHint(R.string.name); - - // Show soft keyboard automatically - this.mEditText.setText(getArguments().getString("hint")); - this.mEditText.requestFocus(); - getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); - this.mEditText.setOnEditorActionListener(this); - - return new AlertDialog.Builder(getActivity()) - .setView(view) - .setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - returnData(); - } - } - ) - .setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - } - ) - .create(); - } - - void returnData() { - EditDialogListener target = (EditDialogListener) getTargetFragment(); - if (target == null) { - target = (EditDialogListener) getActivity(); - } - target.onFinishEditDialog(this.mEditText.getText().toString(), getArguments().getString("hint"), - (Actions) getArguments().getSerializable("action")); - this.dismiss(); - } - - @Override - public boolean onEditorAction(final TextView v, final int actionId, final KeyEvent event) { - if (EditorInfo.IME_ACTION_DONE == actionId) { - returnData(); - return true; - } - return false; - } - - public enum Actions { - NewFile, NewFolder - } - - public interface EditDialogListener { - void onFinishEditDialog(String result, String hint, Actions action); - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.dialogfragment; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.TextView; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.views.DialogHelper; + +// ... +public class EditTextDialog extends DialogFragment implements TextView.OnEditorActionListener { + + private EditText mEditText; + + public static EditTextDialog newInstance(final Actions action) { + return EditTextDialog.newInstance(action, ""); + } + + public static EditTextDialog newInstance(final Actions action, final String hint) { + final EditTextDialog f = new EditTextDialog(); + final Bundle args = new Bundle(); + args.putSerializable("action", action); + args.putString("hint", hint); + f.setArguments(args); + return f; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + final Actions action = (Actions) getArguments().getSerializable("action"); + final String title; + switch (action) { + case NewFile: + title = getString(R.string.file); + break; + case NewFolder: + title = getString(R.string.folder); + break; + default: + title = null; + break; + } + + View view = new DialogHelper.Builder(getActivity()) + .setTitle(title) + .setView(R.layout.dialog_fragment_edittext) + .createSkeletonView(); + this.mEditText = (EditText) view.findViewById(android.R.id.edit); + this.mEditText.setHint(R.string.name); + + // Show soft keyboard automatically + this.mEditText.setText(getArguments().getString("hint")); + this.mEditText.requestFocus(); + getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + this.mEditText.setOnEditorActionListener(this); + + return new AlertDialog.Builder(getActivity()) + .setView(view) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + returnData(); + } + } + ) + .setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + } + ) + .create(); + } + + void returnData() { + EditDialogListener target = (EditDialogListener) getTargetFragment(); + if (target == null) { + target = (EditDialogListener) getActivity(); + } + target.onFinishEditDialog(this.mEditText.getText().toString(), getArguments().getString("hint"), + (Actions) getArguments().getSerializable("action")); + this.dismiss(); + } + + @Override + public boolean onEditorAction(final TextView v, final int actionId, final KeyEvent event) { + if (EditorInfo.IME_ACTION_DONE == actionId) { + returnData(); + return true; + } + return false; + } + + public enum Actions { + NewFile, NewFolder + } + + public interface EditDialogListener { + void onFinishEditDialog(String result, String hint, Actions action); + } } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EncodingDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EncodingDialog.java index b89b3e7..369d4a7 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EncodingDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EncodingDialog.java @@ -1,120 +1,120 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.dialogfragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.os.Bundle; -import android.support.v7.widget.SwitchCompat; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.CompoundButton; -import android.widget.ListView; - -import org.mozilla.universalchardet.Constants; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.preferences.PreferenceHelper; - -public class EncodingDialog extends DialogFragment implements AdapterView.OnItemClickListener { - - private final String[] encodings = new String[]{ - Constants.CHARSET_BIG5, - Constants.CHARSET_EUC_JP, - Constants.CHARSET_EUC_KR, - Constants.CHARSET_EUC_TW, - Constants.CHARSET_GB18030, - "GB2312", - Constants.CHARSET_IBM855, - Constants.CHARSET_IBM866, - Constants.CHARSET_ISO_2022_CN, - Constants.CHARSET_ISO_2022_JP, - Constants.CHARSET_ISO_2022_KR, - Constants.CHARSET_ISO_8859_5, - Constants.CHARSET_ISO_8859_7, - Constants.CHARSET_ISO_8859_8, - Constants.CHARSET_KOI8_R, - Constants.CHARSET_MACCYRILLIC, - Constants.CHARSET_SHIFT_JIS, - Constants.CHARSET_UTF_16BE, - Constants.CHARSET_UTF_16LE, - Constants.CHARSET_UTF_32BE, - Constants.CHARSET_UTF_32LE, - Constants.CHARSET_UTF_8, - Constants.CHARSET_WINDOWS_1251, - Constants.CHARSET_WINDOWS_1252, - Constants.CHARSET_WINDOWS_1253, - Constants.CHARSET_WINDOWS_1255 - }; - private ListView list; - - public static EncodingDialog newInstance() { - final EncodingDialog f = new EncodingDialog(); - return f; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_encoding_list, null); - list = (ListView) view.findViewById(android.R.id.list); - SwitchCompat autoencoding = (SwitchCompat) view.findViewById(android.R.id.checkbox); - autoencoding.setChecked(PreferenceHelper.getAutoEncoding(getActivity())); - - autoencoding.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setAutoencoding(getActivity(), isChecked); - } - }); - - list.setAdapter(new ArrayAdapter<>(getActivity(), R.layout.item_single_choice, encodings)); - list.setOnItemClickListener(this); - - String currentEncoding = PreferenceHelper.getEncoding(getActivity()); - - for (int i = 0; i < encodings.length; i++) { - if (currentEncoding.equals(encodings[i])) { - list.setItemChecked(i, true); - } - - } - - return new AlertDialog.Builder(getActivity()) - .setView(view) - .create(); - } - - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - DialogListener target = (DialogListener) getTargetFragment(); - if (target == null) { - target = (DialogListener) getActivity(); - } - target.onEncodingSelected(encodings[position]); - this.dismiss(); - } - - public interface DialogListener { - void onEncodingSelected(String result); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.dialogfragment; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.os.Bundle; +import android.support.v7.widget.SwitchCompat; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.CompoundButton; +import android.widget.ListView; + +import org.mozilla.universalchardet.Constants; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.preferences.PreferenceHelper; + +public class EncodingDialog extends DialogFragment implements AdapterView.OnItemClickListener { + + private final String[] encodings = new String[]{ + Constants.CHARSET_BIG5, + Constants.CHARSET_EUC_JP, + Constants.CHARSET_EUC_KR, + Constants.CHARSET_EUC_TW, + Constants.CHARSET_GB18030, + "GB2312", + Constants.CHARSET_IBM855, + Constants.CHARSET_IBM866, + Constants.CHARSET_ISO_2022_CN, + Constants.CHARSET_ISO_2022_JP, + Constants.CHARSET_ISO_2022_KR, + Constants.CHARSET_ISO_8859_5, + Constants.CHARSET_ISO_8859_7, + Constants.CHARSET_ISO_8859_8, + Constants.CHARSET_KOI8_R, + Constants.CHARSET_MACCYRILLIC, + Constants.CHARSET_SHIFT_JIS, + Constants.CHARSET_UTF_16BE, + Constants.CHARSET_UTF_16LE, + Constants.CHARSET_UTF_32BE, + Constants.CHARSET_UTF_32LE, + Constants.CHARSET_UTF_8, + Constants.CHARSET_WINDOWS_1251, + Constants.CHARSET_WINDOWS_1252, + Constants.CHARSET_WINDOWS_1253, + Constants.CHARSET_WINDOWS_1255 + }; + private ListView list; + + public static EncodingDialog newInstance() { + final EncodingDialog f = new EncodingDialog(); + return f; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_encoding_list, null); + list = (ListView) view.findViewById(android.R.id.list); + SwitchCompat autoencoding = (SwitchCompat) view.findViewById(android.R.id.checkbox); + autoencoding.setChecked(PreferenceHelper.getAutoEncoding(getActivity())); + + autoencoding.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setAutoencoding(getActivity(), isChecked); + } + }); + + list.setAdapter(new ArrayAdapter<>(getActivity(), R.layout.item_single_choice, encodings)); + list.setOnItemClickListener(this); + + String currentEncoding = PreferenceHelper.getEncoding(getActivity()); + + for (int i = 0; i < encodings.length; i++) { + if (currentEncoding.equals(encodings[i])) { + list.setItemChecked(i, true); + } + + } + + return new AlertDialog.Builder(getActivity()) + .setView(view) + .create(); + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + DialogListener target = (DialogListener) getTargetFragment(); + if (target == null) { + target = (DialogListener) getActivity(); + } + target.onEncodingSelected(encodings[position]); + this.dismiss(); + } + + public interface DialogListener { + void onEncodingSelected(String result); + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FileInfoDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FileInfoDialog.java index aad6ecf..dfc93df 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FileInfoDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FileInfoDialog.java @@ -1,97 +1,97 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.dialogfragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; -import android.os.Bundle; -import android.view.View; -import android.widget.ListView; - -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.util.Date; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.adapter.AdapterTwoItem; -import sharedcode.turboeditor.views.DialogHelper; - -// ... -public class FileInfoDialog extends DialogFragment { - - public static FileInfoDialog newInstance(String filePath) { - final FileInfoDialog f = new FileInfoDialog(); - final Bundle args = new Bundle(); - args.putString("filePath", filePath); - f.setArguments(args); - return f; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - View view = new DialogHelper.Builder(getActivity()) - .setTitle(R.string.info) - .setView(R.layout.dialog_fragment_file_info) - .createSkeletonView(); - //final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_file_info, null); - - ListView list = (ListView) view.findViewById(android.R.id.list); - - File file = new File(getArguments().getString("filePath")); - - // Get the last modification information. - Long lastModified = file.lastModified(); - - // Create a new date object and pass last modified information - // to the date object. - Date date = new Date(lastModified); - - String[] lines1 = { - getString(R.string.name), - getString(R.string.folder), - getString(R.string.size), - getString(R.string.modification_date) - }; - String[] lines2 = { - file.getName(), - file.getParent(), - FileUtils.byteCountToDisplaySize(file.length()), - date.toString() - }; - - list.setAdapter(new AdapterTwoItem(getActivity(), lines1, lines2)); - - - return new AlertDialog.Builder(getActivity()) - .setView(view) - .setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - } - } - ) - .create(); - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.dialogfragment; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.View; +import android.widget.ListView; + +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.Date; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.adapter.AdapterTwoItem; +import sharedcode.turboeditor.views.DialogHelper; + +// ... +public class FileInfoDialog extends DialogFragment { + + public static FileInfoDialog newInstance(String filePath) { + final FileInfoDialog f = new FileInfoDialog(); + final Bundle args = new Bundle(); + args.putString("filePath", filePath); + f.setArguments(args); + return f; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + View view = new DialogHelper.Builder(getActivity()) + .setTitle(R.string.info) + .setView(R.layout.dialog_fragment_file_info) + .createSkeletonView(); + //final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_file_info, null); + + ListView list = (ListView) view.findViewById(android.R.id.list); + + File file = new File(getArguments().getString("filePath")); + + // Get the last modification information. + Long lastModified = file.lastModified(); + + // Create a new date object and pass last modified information + // to the date object. + Date date = new Date(lastModified); + + String[] lines1 = { + getString(R.string.name), + getString(R.string.folder), + getString(R.string.size), + getString(R.string.modification_date) + }; + String[] lines2 = { + file.getName(), + file.getParent(), + FileUtils.byteCountToDisplaySize(file.length()), + date.toString() + }; + + list.setAdapter(new AdapterTwoItem(getActivity(), lines1, lines2)); + + + return new AlertDialog.Builder(getActivity()) + .setView(view) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + } + ) + .create(); + } } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FindTextDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FindTextDialog.java index bdf1f7b..a628871 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FindTextDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FindTextDialog.java @@ -1,207 +1,207 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.dialogfragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; -import android.os.AsyncTask; -import android.os.Bundle; -import android.view.View; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.EditText; -import android.widget.Toast; - -import java.util.LinkedList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.texteditor.SearchResult; -import sharedcode.turboeditor.views.DialogHelper; - -// ... -public class FindTextDialog extends DialogFragment { - - private EditText textToFind, textToReplace; - private CheckBox regexCheck, replaceCheck, matchCaseCheck; - - public static FindTextDialog newInstance(String allText) { - final FindTextDialog f = new FindTextDialog(); - final Bundle args = new Bundle(); - args.putString("allText", allText); - f.setArguments(args); - return f; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - //final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_find_text, null); - - View view = new DialogHelper.Builder(getActivity()) - .setTitle(R.string.find) - .setView(R.layout.dialog_fragment_find_text) - .createSkeletonView(); - - this.textToFind = (EditText) view.findViewById(R.id.text_to_find); - this.textToReplace = (EditText) view.findViewById(R.id.text_to_replace); - this.regexCheck = (CheckBox) view.findViewById(R.id.regex_check); - this.replaceCheck = (CheckBox) view.findViewById(R.id.replace_check); - this.matchCaseCheck = (CheckBox) view.findViewById(R.id.match_case_check); - - replaceCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - textToReplace.setVisibility(isChecked ? View.VISIBLE : View.GONE); - } - }); - - return new AlertDialog.Builder(getActivity()) - .setView(view) - .setPositiveButton(R.string.find, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - } - } - ) - .setNegativeButton(android.R.string.cancel, null) - .create(); - } - - @Override - public void onStart() { - super.onStart(); //super.onStart() is where dialog.show() is actually called on the underlying dialog, so we have to do it after this point - AlertDialog d = (AlertDialog) getDialog(); - if (d != null) { - Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE); - positiveButton.setText(getString(R.string.find)); - positiveButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - returnData(); - } - }); - - Button negativeButton = (Button) d.getButton(Dialog.BUTTON_NEGATIVE); - negativeButton.setText(getString(android.R.string.cancel)); - negativeButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - dismiss(); - } - }); - } - } - - void returnData() { - if (textToFind.getText().toString().isEmpty()) { - this.dismiss(); - } else { - // we disable the okButton while we search - new SearchTask().execute(); - } - } - - public interface SearchDialogInterface { - void onSearchDone(SearchResult searchResult); - } - - private class SearchTask extends AsyncTask { - - LinkedList foundIndex; - boolean foundSomething; - - @Override - protected Void doInBackground(Void... params) { - String allText = getArguments().getString("allText"); - String whatToSearch = textToFind.getText().toString(); - boolean caseSensitive = matchCaseCheck.isChecked(); - boolean isRegex = regexCheck.isChecked(); - foundIndex = new LinkedList<>(); - Matcher matcher = null; - foundSomething = false; - - if (isRegex) { - try { - if (caseSensitive) - matcher = Pattern.compile(whatToSearch, Pattern.MULTILINE).matcher(allText); - else - matcher = Pattern.compile(whatToSearch, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE).matcher(allText); - } catch (Exception e) { - isRegex = false; - } - } - - if (isRegex) { - while (matcher.find()) { - foundSomething = true; - - foundIndex.add(matcher.start()); - } - } else { - if (caseSensitive == false) { // by default is case sensitive - whatToSearch = whatToSearch.toLowerCase(); - allText = allText.toLowerCase(); - } - int index = allText.indexOf(whatToSearch); - while (index >= 0) { - foundSomething = true; - - foundIndex.add(index); - - index = allText.indexOf(whatToSearch, index + 1); - } - } - - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if (foundSomething) { - // the class that called this Dialog should implement the SearchDialogIterface - SearchDialogInterface searchDialogInterface; - searchDialogInterface = ((SearchDialogInterface) getTargetFragment()); - if (searchDialogInterface == null) - searchDialogInterface = ((SearchDialogInterface) getActivity()); - - // if who called this has not implemented the interface we return nothing - if (searchDialogInterface == null) - return; - // else we return positions and other things - else { - SearchResult searchResult = new SearchResult(foundIndex, textToFind.length(), replaceCheck.isChecked(), textToReplace.getText().toString()); - searchDialogInterface.onSearchDone(searchResult); - } - } else { - - } - Toast.makeText(getActivity(), String.format(getString(R.string.occurrences_found), foundIndex.size()), Toast.LENGTH_SHORT).show(); - // dismiss the dialog - FindTextDialog.this.dismiss(); - } - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.dialogfragment; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.AsyncTask; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.Toast; + +import java.util.LinkedList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.texteditor.SearchResult; +import sharedcode.turboeditor.views.DialogHelper; + +// ... +public class FindTextDialog extends DialogFragment { + + private EditText textToFind, textToReplace; + private CheckBox regexCheck, replaceCheck, matchCaseCheck; + + public static FindTextDialog newInstance(String allText) { + final FindTextDialog f = new FindTextDialog(); + final Bundle args = new Bundle(); + args.putString("allText", allText); + f.setArguments(args); + return f; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + //final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_find_text, null); + + View view = new DialogHelper.Builder(getActivity()) + .setTitle(R.string.find) + .setView(R.layout.dialog_fragment_find_text) + .createSkeletonView(); + + this.textToFind = (EditText) view.findViewById(R.id.text_to_find); + this.textToReplace = (EditText) view.findViewById(R.id.text_to_replace); + this.regexCheck = (CheckBox) view.findViewById(R.id.regex_check); + this.replaceCheck = (CheckBox) view.findViewById(R.id.replace_check); + this.matchCaseCheck = (CheckBox) view.findViewById(R.id.match_case_check); + + replaceCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + textToReplace.setVisibility(isChecked ? View.VISIBLE : View.GONE); + } + }); + + return new AlertDialog.Builder(getActivity()) + .setView(view) + .setPositiveButton(R.string.find, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + } + ) + .setNegativeButton(android.R.string.cancel, null) + .create(); + } + + @Override + public void onStart() { + super.onStart(); //super.onStart() is where dialog.show() is actually called on the underlying dialog, so we have to do it after this point + AlertDialog d = (AlertDialog) getDialog(); + if (d != null) { + Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE); + positiveButton.setText(getString(R.string.find)); + positiveButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + returnData(); + } + }); + + Button negativeButton = (Button) d.getButton(Dialog.BUTTON_NEGATIVE); + negativeButton.setText(getString(android.R.string.cancel)); + negativeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } + } + + void returnData() { + if (textToFind.getText().toString().isEmpty()) { + this.dismiss(); + } else { + // we disable the okButton while we search + new SearchTask().execute(); + } + } + + public interface SearchDialogInterface { + void onSearchDone(SearchResult searchResult); + } + + private class SearchTask extends AsyncTask { + + LinkedList foundIndex; + boolean foundSomething; + + @Override + protected Void doInBackground(Void... params) { + String allText = getArguments().getString("allText"); + String whatToSearch = textToFind.getText().toString(); + boolean caseSensitive = matchCaseCheck.isChecked(); + boolean isRegex = regexCheck.isChecked(); + foundIndex = new LinkedList<>(); + Matcher matcher = null; + foundSomething = false; + + if (isRegex) { + try { + if (caseSensitive) + matcher = Pattern.compile(whatToSearch, Pattern.MULTILINE).matcher(allText); + else + matcher = Pattern.compile(whatToSearch, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE).matcher(allText); + } catch (Exception e) { + isRegex = false; + } + } + + if (isRegex) { + while (matcher.find()) { + foundSomething = true; + + foundIndex.add(matcher.start()); + } + } else { + if (caseSensitive == false) { // by default is case sensitive + whatToSearch = whatToSearch.toLowerCase(); + allText = allText.toLowerCase(); + } + int index = allText.indexOf(whatToSearch); + while (index >= 0) { + foundSomething = true; + + foundIndex.add(index); + + index = allText.indexOf(whatToSearch, index + 1); + } + } + + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if (foundSomething) { + // the class that called this Dialog should implement the SearchDialogIterface + SearchDialogInterface searchDialogInterface; + searchDialogInterface = ((SearchDialogInterface) getTargetFragment()); + if (searchDialogInterface == null) + searchDialogInterface = ((SearchDialogInterface) getActivity()); + + // if who called this has not implemented the interface we return nothing + if (searchDialogInterface == null) + return; + // else we return positions and other things + else { + SearchResult searchResult = new SearchResult(foundIndex, textToFind.length(), replaceCheck.isChecked(), textToReplace.getText().toString()); + searchDialogInterface.onSearchDone(searchResult); + } + } else { + + } + Toast.makeText(getActivity(), String.format(getString(R.string.occurrences_found), foundIndex.size()), Toast.LENGTH_SHORT).show(); + // dismiss the dialog + FindTextDialog.this.dismiss(); + } + } } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NewFileDetailsDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NewFileDetailsDialog.java index f27f65f..14e3b4f 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NewFileDetailsDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NewFileDetailsDialog.java @@ -1,98 +1,98 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.dialogfragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; -import android.os.Bundle; -import android.view.View; -import android.view.WindowManager; -import android.widget.EditText; - -import java.io.File; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.activity.MainActivity; -import sharedcode.turboeditor.preferences.PreferenceHelper; -import sharedcode.turboeditor.task.SaveFileTask; -import sharedcode.turboeditor.views.DialogHelper; - -// ... -public class NewFileDetailsDialog extends DialogFragment { - - private EditText mName; - private EditText mFolder; - - public static NewFileDetailsDialog newInstance(String fileText, String fileEncoding) { - final NewFileDetailsDialog f = new NewFileDetailsDialog(); - final Bundle args = new Bundle(); - args.putString("fileText", fileText); - args.putString("fileEncoding", fileEncoding); - f.setArguments(args); - return f; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - View view = new DialogHelper.Builder(getActivity()) - .setTitle(R.string.file) - .setView(R.layout.dialog_fragment_new_file_details) - .createSkeletonView(); - - this.mName = (EditText) view.findViewById(android.R.id.text1); - this.mFolder = (EditText) view.findViewById(android.R.id.text2); - - this.mName.setText(".txt"); - this.mFolder.setText(PreferenceHelper.getWorkingFolder(getActivity())); - - // Show soft keyboard automatically - this.mName.requestFocus(); - this.mName.setSelection(0); - getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); - - return new AlertDialog.Builder(getActivity()) - .setView(view) - .setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (!mName.getText().toString().isEmpty() && !mFolder.getText().toString().isEmpty()) { - File file = new File(mFolder.getText().toString(), mName.getText().toString()); - new SaveFileTask((MainActivity) getActivity(), file.getPath(), getArguments().getString("fileText"), getArguments().getString("fileEncoding")).execute(); - PreferenceHelper.setWorkingFolder(getActivity(), file.getParent()); - } - } - } - ) - .setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - } - ) - .create(); - } - +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.dialogfragment; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.View; +import android.view.WindowManager; +import android.widget.EditText; + +import java.io.File; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.activity.MainActivity; +import sharedcode.turboeditor.preferences.PreferenceHelper; +import sharedcode.turboeditor.task.SaveFileTask; +import sharedcode.turboeditor.views.DialogHelper; + +// ... +public class NewFileDetailsDialog extends DialogFragment { + + private EditText mName; + private EditText mFolder; + + public static NewFileDetailsDialog newInstance(String fileText, String fileEncoding) { + final NewFileDetailsDialog f = new NewFileDetailsDialog(); + final Bundle args = new Bundle(); + args.putString("fileText", fileText); + args.putString("fileEncoding", fileEncoding); + f.setArguments(args); + return f; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + View view = new DialogHelper.Builder(getActivity()) + .setTitle(R.string.file) + .setView(R.layout.dialog_fragment_new_file_details) + .createSkeletonView(); + + this.mName = (EditText) view.findViewById(android.R.id.text1); + this.mFolder = (EditText) view.findViewById(android.R.id.text2); + + this.mName.setText(".txt"); + this.mFolder.setText(PreferenceHelper.getWorkingFolder(getActivity())); + + // Show soft keyboard automatically + this.mName.requestFocus(); + this.mName.setSelection(0); + getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + + return new AlertDialog.Builder(getActivity()) + .setView(view) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (!mName.getText().toString().isEmpty() && !mFolder.getText().toString().isEmpty()) { + File file = new File(mFolder.getText().toString(), mName.getText().toString()); + new SaveFileTask((MainActivity) getActivity(), file.getPath(), getArguments().getString("fileText"), getArguments().getString("fileEncoding")).execute(); + PreferenceHelper.setWorkingFolder(getActivity(), file.getParent()); + } + } + } + ) + .setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + } + ) + .create(); + } + } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NumberPickerDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NumberPickerDialog.java index 8368647..56f84ae 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NumberPickerDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NumberPickerDialog.java @@ -1,123 +1,123 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.dialogfragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; -import android.os.Bundle; -import android.view.View; -import android.widget.NumberPicker; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.views.DialogHelper; - -// ... -public class NumberPickerDialog extends DialogFragment { - - private NumberPicker mSeekBar; - - public static NumberPickerDialog newInstance(final Actions action) { - return NumberPickerDialog.newInstance(action, 0, 50, 100); - } - - public static NumberPickerDialog newInstance(final Actions action, final int min, final int current, final int max) { - final NumberPickerDialog f = new NumberPickerDialog(); - final Bundle args = new Bundle(); - args.putSerializable("action", action); - args.putInt("min", min); - args.putInt("current", current); - args.putInt("max", max); - f.setArguments(args); - return f; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - Actions action = (Actions) getArguments().getSerializable("action"); - int title; - switch (action){ - case FontSize: - title = R.string.font_size; - break; - case SelectPage: - title = R.string.goto_page; - break; - case GoToLine: - title = R.string.goto_line; - break; - default: - title = R.string.nome_app_turbo_editor; - break; - } - - View view = new DialogHelper.Builder(getActivity()) - .setTitle(title) - .setView(R.layout.dialog_fragment_seekbar) - .createSkeletonView(); - - this.mSeekBar = (NumberPicker) view.findViewById(android.R.id.input); - this.mSeekBar.setMaxValue(getArguments().getInt("max")); - this.mSeekBar.setMinValue(getArguments().getInt("min")); - this.mSeekBar.setValue(getArguments().getInt("current")); - return new AlertDialog.Builder(getActivity()) - //.setTitle(title) - .setView(view) - .setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - returnData(); - } - } - ) - .setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - } - ) - .create(); - } - - void returnData() { - INumberPickerDialog target = (INumberPickerDialog) getTargetFragment(); - if (target == null) { - target = (INumberPickerDialog) getActivity(); - } - target.onNumberPickerDialogDismissed( - (Actions) getArguments().getSerializable("action"), - mSeekBar.getValue() - ); - this.dismiss(); - } - - public enum Actions { - FontSize, SelectPage, GoToLine - } - - public interface INumberPickerDialog { - void onNumberPickerDialogDismissed(Actions action, int value); - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.dialogfragment; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.View; +import android.widget.NumberPicker; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.views.DialogHelper; + +// ... +public class NumberPickerDialog extends DialogFragment { + + private NumberPicker mSeekBar; + + public static NumberPickerDialog newInstance(final Actions action) { + return NumberPickerDialog.newInstance(action, 0, 50, 100); + } + + public static NumberPickerDialog newInstance(final Actions action, final int min, final int current, final int max) { + final NumberPickerDialog f = new NumberPickerDialog(); + final Bundle args = new Bundle(); + args.putSerializable("action", action); + args.putInt("min", min); + args.putInt("current", current); + args.putInt("max", max); + f.setArguments(args); + return f; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + Actions action = (Actions) getArguments().getSerializable("action"); + int title; + switch (action){ + case FontSize: + title = R.string.font_size; + break; + case SelectPage: + title = R.string.goto_page; + break; + case GoToLine: + title = R.string.goto_line; + break; + default: + title = R.string.nome_app_turbo_editor; + break; + } + + View view = new DialogHelper.Builder(getActivity()) + .setTitle(title) + .setView(R.layout.dialog_fragment_seekbar) + .createSkeletonView(); + + this.mSeekBar = (NumberPicker) view.findViewById(android.R.id.input); + this.mSeekBar.setMaxValue(getArguments().getInt("max")); + this.mSeekBar.setMinValue(getArguments().getInt("min")); + this.mSeekBar.setValue(getArguments().getInt("current")); + return new AlertDialog.Builder(getActivity()) + //.setTitle(title) + .setView(view) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + returnData(); + } + } + ) + .setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + } + ) + .create(); + } + + void returnData() { + INumberPickerDialog target = (INumberPickerDialog) getTargetFragment(); + if (target == null) { + target = (INumberPickerDialog) getActivity(); + } + target.onNumberPickerDialogDismissed( + (Actions) getArguments().getSerializable("action"), + mSeekBar.getValue() + ); + this.dismiss(); + } + + public enum Actions { + FontSize, SelectPage, GoToLine + } + + public interface INumberPickerDialog { + void onNumberPickerDialogDismissed(Actions action, int value); + } } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/SaveFileDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/SaveFileDialog.java index 9a4acab..bd7f44c 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/SaveFileDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/SaveFileDialog.java @@ -1,113 +1,113 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.dialogfragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; -import android.os.Bundle; -import android.view.View; - -import org.apache.commons.io.FilenameUtils; - -import java.io.File; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.activity.MainActivity; -import sharedcode.turboeditor.task.SaveFileTask; -import sharedcode.turboeditor.views.DialogHelper; - -public class SaveFileDialog extends DialogFragment { - - public static SaveFileDialog newInstance(String filePath, String text, String encoding) { - return newInstance(filePath, text, encoding, false, ""); - } - - public static SaveFileDialog newInstance(String filePath, String text, String encoding, boolean openNewFileAfter, String pathOfNewFile) { - SaveFileDialog frag = new SaveFileDialog(); - Bundle args = new Bundle(); - args.putString("filePath", filePath); - args.putString("text", text); - args.putString("encoding", encoding); - args.putBoolean("openNewFileAfter", openNewFileAfter); - args.putString("pathOfNewFile", pathOfNewFile); - frag.setArguments(args); - return frag; - } - - - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final String filePath = getArguments().getString("filePath"); - final String text = getArguments().getString("text"); - final String encoding = getArguments().getString("encoding"); - final String fileName = FilenameUtils.getName(filePath); - final File file = new File(filePath); - - View view = new DialogHelper.Builder(getActivity()) - .setIcon(getResources().getDrawable(R.drawable.ic_action_save)) - .setTitle(R.string.salva) - .setMessage(String.format(getString(R.string.save_changes), fileName)) - .createCommonView(); - - return new AlertDialog.Builder(getActivity()) - .setView(view) - .setPositiveButton(R.string.salva, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (!fileName.isEmpty()) - new SaveFileTask((MainActivity) getActivity(), filePath, text, - encoding).execute(); - else { - NewFileDetailsDialog dialogFrag = - NewFileDetailsDialog.newInstance(text, - encoding); - dialogFrag.show(getFragmentManager().beginTransaction(), - "dialog"); - } - } - } - ) - .setNeutralButton(android.R.string.cancel, null) - .setNegativeButton(R.string.no, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - ISaveDialog target = (ISaveDialog) getTargetFragment(); - if (target == null) { - target = (ISaveDialog) getActivity(); - } - target.userDoesntWantToSave( - getArguments().getBoolean("openNewFileAfter"), - getArguments().getString("pathOfNewFile") - ); - } - } - ) - .create(); - } - - public interface ISaveDialog { - void userDoesntWantToSave(boolean openNewFile, String pathOfNewFile); - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.dialogfragment; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.View; + +import org.apache.commons.io.FilenameUtils; + +import java.io.File; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.activity.MainActivity; +import sharedcode.turboeditor.task.SaveFileTask; +import sharedcode.turboeditor.views.DialogHelper; + +public class SaveFileDialog extends DialogFragment { + + public static SaveFileDialog newInstance(String filePath, String text, String encoding) { + return newInstance(filePath, text, encoding, false, ""); + } + + public static SaveFileDialog newInstance(String filePath, String text, String encoding, boolean openNewFileAfter, String pathOfNewFile) { + SaveFileDialog frag = new SaveFileDialog(); + Bundle args = new Bundle(); + args.putString("filePath", filePath); + args.putString("text", text); + args.putString("encoding", encoding); + args.putBoolean("openNewFileAfter", openNewFileAfter); + args.putString("pathOfNewFile", pathOfNewFile); + frag.setArguments(args); + return frag; + } + + + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final String filePath = getArguments().getString("filePath"); + final String text = getArguments().getString("text"); + final String encoding = getArguments().getString("encoding"); + final String fileName = FilenameUtils.getName(filePath); + final File file = new File(filePath); + + View view = new DialogHelper.Builder(getActivity()) + .setIcon(getResources().getDrawable(R.drawable.ic_action_save)) + .setTitle(R.string.salva) + .setMessage(String.format(getString(R.string.save_changes), fileName)) + .createCommonView(); + + return new AlertDialog.Builder(getActivity()) + .setView(view) + .setPositiveButton(R.string.salva, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (!fileName.isEmpty()) + new SaveFileTask((MainActivity) getActivity(), filePath, text, + encoding).execute(); + else { + NewFileDetailsDialog dialogFrag = + NewFileDetailsDialog.newInstance(text, + encoding); + dialogFrag.show(getFragmentManager().beginTransaction(), + "dialog"); + } + } + } + ) + .setNeutralButton(android.R.string.cancel, null) + .setNegativeButton(R.string.no, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + ISaveDialog target = (ISaveDialog) getTargetFragment(); + if (target == null) { + target = (ISaveDialog) getActivity(); + } + target.userDoesntWantToSave( + getArguments().getBoolean("openNewFileAfter"), + getArguments().getString("pathOfNewFile") + ); + } + } + ) + .create(); + } + + public interface ISaveDialog { + void userDoesntWantToSave(boolean openNewFile, String pathOfNewFile); + } } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceHelper.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceHelper.java index 408e575..5b024d1 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceHelper.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceHelper.java @@ -1,188 +1,188 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.preferences; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Environment; -import android.preference.PreferenceManager; - -public final class PreferenceHelper { - - public static final String SD_CARD_ROOT = Environment.getExternalStorageDirectory().getAbsolutePath(); - - private PreferenceHelper() { - } - - // Getter Methods - - private static SharedPreferences getPrefs(Context context) { - return PreferenceManager.getDefaultSharedPreferences(context); - } - - private static SharedPreferences.Editor getEditor(Context context) { - return getPrefs(context).edit(); - } - - public static boolean getUseMonospace(Context context) { - return getPrefs(context).getBoolean("use_monospace", false); - } - - public static boolean getLineNumbers(Context context) { - return getPrefs(context).getBoolean("editor_line_numbers", true); - } - - public static boolean getSyntaxHighlight(Context context) { - return getPrefs(context).getBoolean("editor_syntax_highlight", false); - } - - public static boolean getWrapContent(Context context) { - return getPrefs(context).getBoolean("editor_wrap_content", true); - } - - public static boolean getLightTheme(Context context) { - return getPrefs(context).getBoolean("light_theme", false); - } - - public static boolean getSuggestionActive(Context context) { - return getPrefs(context).getBoolean("suggestion_active", false); - } - - public static boolean getAutoEncoding(Context context) { - return getPrefs(context).getBoolean("autoencoding", true); - } - - public static boolean getSendErrorReports(Context context) { - return getPrefs(context).getBoolean("send_error_reports", true); - } - - public static String getEncoding(Context context) { - return getPrefs(context).getString("editor_encoding", "UTF-8"); - } - - public static int getFontSize(Context context) { - return getPrefs(context).getInt("font_size", 16); - } - - public static String getWorkingFolder(Context context) { - return getPrefs(context).getString("working_folder", SD_CARD_ROOT); - } - - public static String[] getSavedPaths(Context context) { - return getPrefs(context).getString("savedPaths", "").split(","); - } - - public static boolean getPageSystemButtonsPopupShown(Context context) { - return getPrefs(context).getBoolean("page_system_button_popup_shown", false); - } - - public static boolean getAutoSave(Context context) { - return getPrefs(context).getBoolean("auto_save", false); - } - - public static boolean getReadOnly(Context context) { - return getPrefs(context).getBoolean("read_only", false); - } - - public static boolean getIgnoreBackButton(Context context) { - return getPrefs(context).getBoolean("ignore_back_button", false); - } - - public static boolean getSplitText(Context context) { - return getPrefs(context).getBoolean("page_system_active", true); - } - - public static boolean hasDonated(Context context) { - return getPrefs(context).getBoolean("has_donated", false); - } - // Setter methods - - public static void setUseMonospace(Context context, boolean value) { - getEditor(context).putBoolean("use_monospace", value).commit(); - } - - public static void setLineNumbers(Context context, boolean value) { - getEditor(context).putBoolean("editor_line_numbers", value).commit(); - } - - public static void setSyntaxHighlight(Context context, boolean value) { - getEditor(context).putBoolean("editor_syntax_highlight", value).commit(); - } - - public static void setWrapContent(Context context, boolean value) { - getEditor(context).putBoolean("editor_wrap_content", value).commit(); - } - - public static void setAutoencoding(Context context, boolean value) { - getEditor(context).putBoolean("autoencoding", value).commit(); - } - - public static void setFontSize(Context context, int value) { - getEditor(context).putInt("font_size", value).commit(); - } - - public static void setWorkingFolder(Context context, String value) { - getEditor(context).putString("working_folder", value).commit(); - } - - public static void setSavedPaths(Context context, StringBuilder stringBuilder) { - getEditor(context).putString("savedPaths", stringBuilder.toString()).commit(); - } - - public static void setPageSystemButtonsPopupShown(Context context, boolean value) { - getEditor(context).putBoolean("page_system_button_popup_shown", value).commit(); - } - - public static void setReadOnly(Context context, boolean value) { - getEditor(context).putBoolean("read_only", value).commit(); - } - - public static void setHasDonated(Context context, boolean value) { - getEditor(context).putBoolean("has_donated", value).commit(); - } - - public static void setLightTheme(Context context, boolean value) { - getEditor(context).putBoolean("light_theme", value).commit(); - } - - public static void setSuggestionsActive(Context context, boolean value) { - getEditor(context).putBoolean("suggestion_active", value).commit(); - } - - public static void setAutoSave(Context context, boolean value) { - getEditor(context).putBoolean("auto_save", value).commit(); - } - - public static void setIgnoreBackButton(Context context, boolean value) { - getEditor(context).putBoolean("ignore_back_button", value).commit(); - } - - public static void setSplitText(Context context, boolean value) { - getEditor(context).putBoolean("page_system_active", value).commit(); - } - - public static void setSendErrorReport(Context context, boolean value) { - getEditor(context).putBoolean("ignore_back_button", value).commit(); - } - - public static void setEncoding(Context context, String value) { - getEditor(context).putString("editor_encoding", value).commit(); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.preferences; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Environment; +import android.preference.PreferenceManager; + +public final class PreferenceHelper { + + public static final String SD_CARD_ROOT = Environment.getExternalStorageDirectory().getAbsolutePath(); + + private PreferenceHelper() { + } + + // Getter Methods + + private static SharedPreferences getPrefs(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context); + } + + private static SharedPreferences.Editor getEditor(Context context) { + return getPrefs(context).edit(); + } + + public static boolean getUseMonospace(Context context) { + return getPrefs(context).getBoolean("use_monospace", false); + } + + public static boolean getLineNumbers(Context context) { + return getPrefs(context).getBoolean("editor_line_numbers", true); + } + + public static boolean getSyntaxHighlight(Context context) { + return getPrefs(context).getBoolean("editor_syntax_highlight", false); + } + + public static boolean getWrapContent(Context context) { + return getPrefs(context).getBoolean("editor_wrap_content", true); + } + + public static boolean getLightTheme(Context context) { + return getPrefs(context).getBoolean("light_theme", false); + } + + public static boolean getSuggestionActive(Context context) { + return getPrefs(context).getBoolean("suggestion_active", false); + } + + public static boolean getAutoEncoding(Context context) { + return getPrefs(context).getBoolean("autoencoding", true); + } + + public static boolean getSendErrorReports(Context context) { + return getPrefs(context).getBoolean("send_error_reports", true); + } + + public static String getEncoding(Context context) { + return getPrefs(context).getString("editor_encoding", "UTF-8"); + } + + public static int getFontSize(Context context) { + return getPrefs(context).getInt("font_size", 16); + } + + public static String getWorkingFolder(Context context) { + return getPrefs(context).getString("working_folder", SD_CARD_ROOT); + } + + public static String[] getSavedPaths(Context context) { + return getPrefs(context).getString("savedPaths", "").split(","); + } + + public static boolean getPageSystemButtonsPopupShown(Context context) { + return getPrefs(context).getBoolean("page_system_button_popup_shown", false); + } + + public static boolean getAutoSave(Context context) { + return getPrefs(context).getBoolean("auto_save", false); + } + + public static boolean getReadOnly(Context context) { + return getPrefs(context).getBoolean("read_only", false); + } + + public static boolean getIgnoreBackButton(Context context) { + return getPrefs(context).getBoolean("ignore_back_button", false); + } + + public static boolean getSplitText(Context context) { + return getPrefs(context).getBoolean("page_system_active", true); + } + + public static boolean hasDonated(Context context) { + return getPrefs(context).getBoolean("has_donated", false); + } + // Setter methods + + public static void setUseMonospace(Context context, boolean value) { + getEditor(context).putBoolean("use_monospace", value).commit(); + } + + public static void setLineNumbers(Context context, boolean value) { + getEditor(context).putBoolean("editor_line_numbers", value).commit(); + } + + public static void setSyntaxHighlight(Context context, boolean value) { + getEditor(context).putBoolean("editor_syntax_highlight", value).commit(); + } + + public static void setWrapContent(Context context, boolean value) { + getEditor(context).putBoolean("editor_wrap_content", value).commit(); + } + + public static void setAutoencoding(Context context, boolean value) { + getEditor(context).putBoolean("autoencoding", value).commit(); + } + + public static void setFontSize(Context context, int value) { + getEditor(context).putInt("font_size", value).commit(); + } + + public static void setWorkingFolder(Context context, String value) { + getEditor(context).putString("working_folder", value).commit(); + } + + public static void setSavedPaths(Context context, StringBuilder stringBuilder) { + getEditor(context).putString("savedPaths", stringBuilder.toString()).commit(); + } + + public static void setPageSystemButtonsPopupShown(Context context, boolean value) { + getEditor(context).putBoolean("page_system_button_popup_shown", value).commit(); + } + + public static void setReadOnly(Context context, boolean value) { + getEditor(context).putBoolean("read_only", value).commit(); + } + + public static void setHasDonated(Context context, boolean value) { + getEditor(context).putBoolean("has_donated", value).commit(); + } + + public static void setLightTheme(Context context, boolean value) { + getEditor(context).putBoolean("light_theme", value).commit(); + } + + public static void setSuggestionsActive(Context context, boolean value) { + getEditor(context).putBoolean("suggestion_active", value).commit(); + } + + public static void setAutoSave(Context context, boolean value) { + getEditor(context).putBoolean("auto_save", value).commit(); + } + + public static void setIgnoreBackButton(Context context, boolean value) { + getEditor(context).putBoolean("ignore_back_button", value).commit(); + } + + public static void setSplitText(Context context, boolean value) { + getEditor(context).putBoolean("page_system_active", value).commit(); + } + + public static void setSendErrorReport(Context context, boolean value) { + getEditor(context).putBoolean("ignore_back_button", value).commit(); + } + + public static void setEncoding(Context context, String value) { + getEditor(context).putString("editor_encoding", value).commit(); + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/SettingsFragment.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/SettingsFragment.java index 8a51d4c..5db0fc2 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/SettingsFragment.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/SettingsFragment.java @@ -1,269 +1,269 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.preferences; - -import android.app.Fragment; -import android.os.Bundle; -import android.support.v7.widget.SwitchCompat; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CompoundButton; -import android.widget.TextView; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.activity.MainActivity; -import sharedcode.turboeditor.dialogfragment.EncodingDialog; -import sharedcode.turboeditor.dialogfragment.NumberPickerDialog; -import sharedcode.turboeditor.util.ProCheckUtils; -import sharedcode.turboeditor.util.ViewUtils; -import sharedcode.turboeditor.views.DialogHelper; - -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.ENCODING; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.FONT_SIZE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.LINE_NUMERS; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.MONOSPACE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.READ_ONLY; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.SYNTAX; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.TEXT_SUGGESTIONS; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.WRAP_CONTENT; - -public class SettingsFragment extends Fragment implements NumberPickerDialog.INumberPickerDialog, EncodingDialog.DialogListener { - - // Editor Variables - private boolean sLineNumbers; - private boolean sColorSyntax; - private boolean sWrapContent; - private boolean sUseMonospace; - private boolean sReadOnly; - - private boolean sLightTheme; - private boolean sSuggestions; - private boolean sAutoSave; - private boolean sIgnoreBackButton; - private boolean sSplitText; - private boolean sErrorReports; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - sUseMonospace = PreferenceHelper.getUseMonospace(getActivity()); - sColorSyntax = PreferenceHelper.getSyntaxHighlight(getActivity()); - sWrapContent = PreferenceHelper.getWrapContent(getActivity()); - sLineNumbers = PreferenceHelper.getLineNumbers(getActivity()); - sReadOnly = PreferenceHelper.getReadOnly(getActivity()); - - sLightTheme = PreferenceHelper.getLightTheme(getActivity()); - sSuggestions = PreferenceHelper.getSuggestionActive(getActivity()); - sAutoSave = PreferenceHelper.getAutoSave(getActivity()); - sIgnoreBackButton = PreferenceHelper.getIgnoreBackButton(getActivity()); - sSplitText = PreferenceHelper.getSplitText(getActivity()); - sErrorReports = PreferenceHelper.getSendErrorReports(getActivity()); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Our custom layout - final View rootView = inflater.inflate(R.layout.fragment_settings, container, false); - final SwitchCompat swLineNumbers, swSyntax, swWrapContent, swMonospace, swReadOnly; - final SwitchCompat swLightTheme, swSuggestions, swAutoSave, swIgnoreBackButton, swSplitText, swErrorReports; - - swLineNumbers = (SwitchCompat) rootView.findViewById(R.id.switch_line_numbers); - swSyntax = (SwitchCompat) rootView.findViewById(R.id.switch_syntax); - swWrapContent = (SwitchCompat) rootView.findViewById(R.id.switch_wrap_content); - swMonospace = (SwitchCompat) rootView.findViewById(R.id.switch_monospace); - swReadOnly = (SwitchCompat) rootView.findViewById(R.id.switch_read_only); - - swLightTheme = (SwitchCompat) rootView.findViewById(R.id.switch_light_theme); - swSuggestions = (SwitchCompat) rootView.findViewById(R.id.switch_suggestions_active); - swAutoSave = (SwitchCompat) rootView.findViewById(R.id.switch_auto_save); - swIgnoreBackButton = (SwitchCompat) rootView.findViewById(R.id.switch_ignore_backbutton); - swSplitText = (SwitchCompat) rootView.findViewById(R.id.switch_page_system); - swErrorReports = (SwitchCompat) rootView.findViewById(R.id.switch_send_error_reports); - - swLineNumbers.setChecked(sLineNumbers); - swSyntax.setChecked(sColorSyntax); - swWrapContent.setChecked(sWrapContent); - swMonospace.setChecked(sUseMonospace); - swReadOnly.setChecked(sReadOnly); - - swLightTheme.setChecked(sLightTheme); - swSuggestions.setChecked(sSuggestions); - swAutoSave.setChecked(sAutoSave); - swIgnoreBackButton.setChecked(sIgnoreBackButton); - swSplitText.setChecked(sSplitText); - swErrorReports.setChecked(sErrorReports); - - TextView fontSizeView, encodingView, donateView, extraOptionsView; - fontSizeView = (TextView) rootView.findViewById(R.id.drawer_button_font_size); - encodingView = (TextView) rootView.findViewById(R.id.drawer_button_encoding); - extraOptionsView = (TextView) rootView.findViewById(R.id.drawer_button_extra_options); - donateView = (TextView) rootView.findViewById(R.id.drawer_button_go_pro); - - if(ProCheckUtils.isPro(getActivity(), false)) - ViewUtils.setVisible(donateView, false); - - swLineNumbers.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setLineNumbers(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(LINE_NUMERS)); - } - }); - - swSyntax.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - sColorSyntax = isChecked; - PreferenceHelper.setSyntaxHighlight(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(SYNTAX)); - - } - }); - - swWrapContent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setWrapContent(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(WRAP_CONTENT)); - } - }); - - swMonospace.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - sUseMonospace = isChecked; - PreferenceHelper.setUseMonospace(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(MONOSPACE)); - - } - }); - - swReadOnly.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setReadOnly(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(READ_ONLY)); - } - }); - - fontSizeView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - int fontMax = 36; - int fontCurrent = //(int) (mEditor.getTextSize() / scaledDensity); - //fontMax / 2; - PreferenceHelper.getFontSize(getActivity()); - NumberPickerDialog dialogFrag = NumberPickerDialog.newInstance(NumberPickerDialog - .Actions - .FontSize, 1, fontCurrent, fontMax); - dialogFrag.setTargetFragment(SettingsFragment.this, 0); - dialogFrag.show(getFragmentManager().beginTransaction(), "dialog"); - } - }); - - encodingView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - EncodingDialog dialogFrag = EncodingDialog.newInstance(); - dialogFrag.setTargetFragment(SettingsFragment.this, 0); - dialogFrag.show(getFragmentManager().beginTransaction(), "dialog"); - } - }); - - extraOptionsView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - View otherOptions = rootView.findViewById(R.id.other_options); - boolean isVisible = otherOptions.getVisibility() == View.VISIBLE; - ViewUtils.setVisible(otherOptions, !isVisible); - } - }); - - donateView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - DialogHelper.showDonateDialog(getActivity()); - } - }); - - swLightTheme.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setLightTheme(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(THEME_CHANGE)); - } - }); - - swSuggestions.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setSuggestionsActive(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(TEXT_SUGGESTIONS)); - } - }); - - swAutoSave.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setAutoSave(getActivity(), isChecked); - } - }); - - swIgnoreBackButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setIgnoreBackButton(getActivity(), isChecked); - } - }); - - swSplitText.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setSplitText(getActivity(), isChecked); - } - }); - - swErrorReports.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - PreferenceHelper.setSendErrorReport(getActivity(), isChecked); - } - }); - - return rootView; - } - - @Override - public void onNumberPickerDialogDismissed(NumberPickerDialog.Actions action, int value) { - PreferenceHelper.setFontSize(getActivity(), value); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(FONT_SIZE)); - - } - - @Override - public void onEncodingSelected(String result) { - PreferenceHelper.setEncoding(getActivity(), result); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(ENCODING)); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.preferences; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.v7.widget.SwitchCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.TextView; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.activity.MainActivity; +import sharedcode.turboeditor.dialogfragment.EncodingDialog; +import sharedcode.turboeditor.dialogfragment.NumberPickerDialog; +import sharedcode.turboeditor.util.ProCheckUtils; +import sharedcode.turboeditor.util.ViewUtils; +import sharedcode.turboeditor.views.DialogHelper; + +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.ENCODING; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.FONT_SIZE; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.LINE_NUMERS; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.MONOSPACE; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.READ_ONLY; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.SYNTAX; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.TEXT_SUGGESTIONS; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE; +import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.WRAP_CONTENT; + +public class SettingsFragment extends Fragment implements NumberPickerDialog.INumberPickerDialog, EncodingDialog.DialogListener { + + // Editor Variables + private boolean sLineNumbers; + private boolean sColorSyntax; + private boolean sWrapContent; + private boolean sUseMonospace; + private boolean sReadOnly; + + private boolean sLightTheme; + private boolean sSuggestions; + private boolean sAutoSave; + private boolean sIgnoreBackButton; + private boolean sSplitText; + private boolean sErrorReports; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + sUseMonospace = PreferenceHelper.getUseMonospace(getActivity()); + sColorSyntax = PreferenceHelper.getSyntaxHighlight(getActivity()); + sWrapContent = PreferenceHelper.getWrapContent(getActivity()); + sLineNumbers = PreferenceHelper.getLineNumbers(getActivity()); + sReadOnly = PreferenceHelper.getReadOnly(getActivity()); + + sLightTheme = PreferenceHelper.getLightTheme(getActivity()); + sSuggestions = PreferenceHelper.getSuggestionActive(getActivity()); + sAutoSave = PreferenceHelper.getAutoSave(getActivity()); + sIgnoreBackButton = PreferenceHelper.getIgnoreBackButton(getActivity()); + sSplitText = PreferenceHelper.getSplitText(getActivity()); + sErrorReports = PreferenceHelper.getSendErrorReports(getActivity()); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Our custom layout + final View rootView = inflater.inflate(R.layout.fragment_settings, container, false); + final SwitchCompat swLineNumbers, swSyntax, swWrapContent, swMonospace, swReadOnly; + final SwitchCompat swLightTheme, swSuggestions, swAutoSave, swIgnoreBackButton, swSplitText, swErrorReports; + + swLineNumbers = (SwitchCompat) rootView.findViewById(R.id.switch_line_numbers); + swSyntax = (SwitchCompat) rootView.findViewById(R.id.switch_syntax); + swWrapContent = (SwitchCompat) rootView.findViewById(R.id.switch_wrap_content); + swMonospace = (SwitchCompat) rootView.findViewById(R.id.switch_monospace); + swReadOnly = (SwitchCompat) rootView.findViewById(R.id.switch_read_only); + + swLightTheme = (SwitchCompat) rootView.findViewById(R.id.switch_light_theme); + swSuggestions = (SwitchCompat) rootView.findViewById(R.id.switch_suggestions_active); + swAutoSave = (SwitchCompat) rootView.findViewById(R.id.switch_auto_save); + swIgnoreBackButton = (SwitchCompat) rootView.findViewById(R.id.switch_ignore_backbutton); + swSplitText = (SwitchCompat) rootView.findViewById(R.id.switch_page_system); + swErrorReports = (SwitchCompat) rootView.findViewById(R.id.switch_send_error_reports); + + swLineNumbers.setChecked(sLineNumbers); + swSyntax.setChecked(sColorSyntax); + swWrapContent.setChecked(sWrapContent); + swMonospace.setChecked(sUseMonospace); + swReadOnly.setChecked(sReadOnly); + + swLightTheme.setChecked(sLightTheme); + swSuggestions.setChecked(sSuggestions); + swAutoSave.setChecked(sAutoSave); + swIgnoreBackButton.setChecked(sIgnoreBackButton); + swSplitText.setChecked(sSplitText); + swErrorReports.setChecked(sErrorReports); + + TextView fontSizeView, encodingView, donateView, extraOptionsView; + fontSizeView = (TextView) rootView.findViewById(R.id.drawer_button_font_size); + encodingView = (TextView) rootView.findViewById(R.id.drawer_button_encoding); + extraOptionsView = (TextView) rootView.findViewById(R.id.drawer_button_extra_options); + donateView = (TextView) rootView.findViewById(R.id.drawer_button_go_pro); + + if(ProCheckUtils.isPro(getActivity(), false)) + ViewUtils.setVisible(donateView, false); + + swLineNumbers.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setLineNumbers(getActivity(), isChecked); + ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(LINE_NUMERS)); + } + }); + + swSyntax.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + sColorSyntax = isChecked; + PreferenceHelper.setSyntaxHighlight(getActivity(), isChecked); + ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(SYNTAX)); + + } + }); + + swWrapContent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setWrapContent(getActivity(), isChecked); + ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(WRAP_CONTENT)); + } + }); + + swMonospace.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + sUseMonospace = isChecked; + PreferenceHelper.setUseMonospace(getActivity(), isChecked); + ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(MONOSPACE)); + + } + }); + + swReadOnly.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setReadOnly(getActivity(), isChecked); + ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(READ_ONLY)); + } + }); + + fontSizeView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + int fontMax = 36; + int fontCurrent = //(int) (mEditor.getTextSize() / scaledDensity); + //fontMax / 2; + PreferenceHelper.getFontSize(getActivity()); + NumberPickerDialog dialogFrag = NumberPickerDialog.newInstance(NumberPickerDialog + .Actions + .FontSize, 1, fontCurrent, fontMax); + dialogFrag.setTargetFragment(SettingsFragment.this, 0); + dialogFrag.show(getFragmentManager().beginTransaction(), "dialog"); + } + }); + + encodingView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + EncodingDialog dialogFrag = EncodingDialog.newInstance(); + dialogFrag.setTargetFragment(SettingsFragment.this, 0); + dialogFrag.show(getFragmentManager().beginTransaction(), "dialog"); + } + }); + + extraOptionsView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + View otherOptions = rootView.findViewById(R.id.other_options); + boolean isVisible = otherOptions.getVisibility() == View.VISIBLE; + ViewUtils.setVisible(otherOptions, !isVisible); + } + }); + + donateView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + DialogHelper.showDonateDialog(getActivity()); + } + }); + + swLightTheme.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setLightTheme(getActivity(), isChecked); + ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(THEME_CHANGE)); + } + }); + + swSuggestions.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setSuggestionsActive(getActivity(), isChecked); + ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(TEXT_SUGGESTIONS)); + } + }); + + swAutoSave.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setAutoSave(getActivity(), isChecked); + } + }); + + swIgnoreBackButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setIgnoreBackButton(getActivity(), isChecked); + } + }); + + swSplitText.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setSplitText(getActivity(), isChecked); + } + }); + + swErrorReports.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + PreferenceHelper.setSendErrorReport(getActivity(), isChecked); + } + }); + + return rootView; + } + + @Override + public void onNumberPickerDialogDismissed(NumberPickerDialog.Actions action, int value) { + PreferenceHelper.setFontSize(getActivity(), value); + ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(FONT_SIZE)); + + } + + @Override + public void onEncodingSelected(String result) { + PreferenceHelper.setEncoding(getActivity(), result); + ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(ENCODING)); + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/root/LinuxShell.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/root/LinuxShell.java index 82e2e7c..8162dd2 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/root/LinuxShell.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/root/LinuxShell.java @@ -1,77 +1,77 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.root; - -import android.util.Log; - -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class LinuxShell { - - private static final String UNIX_ESCAPE_EXPRESSION = "(\\(|\\)|\\[|\\]|\\s|\'|\"|`|\\{|\\}|&|\\\\|\\?)"; - - public static String getCommandLineString(String input) { - return input.replaceAll(UNIX_ESCAPE_EXPRESSION, "\\\\$1"); - } - - public static BufferedReader execute(String cmd) { - BufferedReader reader = null; - try { - Process process = Runtime.getRuntime().exec("su"); - DataOutputStream os = new DataOutputStream( - process.getOutputStream()); - os.writeBytes(cmd + "\n"); - os.writeBytes("exit\n"); - reader = new BufferedReader(new InputStreamReader( - process.getInputStream())); - String err = (new BufferedReader(new InputStreamReader( - process.getErrorStream()))).readLine(); - os.flush(); - - if (process.waitFor() != 0 || (!"".equals(err) && null != err) - && containsIllegals(err) != true) { - Log.e("Root Error, cmd: " + cmd, err); - return null; - } - return reader; - - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static boolean containsIllegals(String toExamine) { - // checks for "+" sign so the program doesn't throw an error when its - // not erroring. - Pattern pattern = Pattern.compile("[+]"); - Matcher matcher = pattern.matcher(toExamine); - return matcher.find(); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.root; + +import android.util.Log; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LinuxShell { + + private static final String UNIX_ESCAPE_EXPRESSION = "(\\(|\\)|\\[|\\]|\\s|\'|\"|`|\\{|\\}|&|\\\\|\\?)"; + + public static String getCommandLineString(String input) { + return input.replaceAll(UNIX_ESCAPE_EXPRESSION, "\\\\$1"); + } + + public static BufferedReader execute(String cmd) { + BufferedReader reader = null; + try { + Process process = Runtime.getRuntime().exec("su"); + DataOutputStream os = new DataOutputStream( + process.getOutputStream()); + os.writeBytes(cmd + "\n"); + os.writeBytes("exit\n"); + reader = new BufferedReader(new InputStreamReader( + process.getInputStream())); + String err = (new BufferedReader(new InputStreamReader( + process.getErrorStream()))).readLine(); + os.flush(); + + if (process.waitFor() != 0 || (!"".equals(err) && null != err) + && containsIllegals(err) != true) { + Log.e("Root Error, cmd: " + cmd, err); + return null; + } + return reader; + + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static boolean containsIllegals(String toExamine) { + // checks for "+" sign so the program doesn't throw an error when its + // not erroring. + Pattern pattern = Pattern.compile("[+]"); + Matcher matcher = pattern.matcher(toExamine); + return matcher.find(); + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/root/RootUtils.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/root/RootUtils.java index 7ed8115..d0c30bf 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/root/RootUtils.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/root/RootUtils.java @@ -1,101 +1,101 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -/** - * 920 Text Editor 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. - * - * 920 Text Editor 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 920 Text Editor. If not, see . - */ - -package sharedcode.turboeditor.root; - -import android.content.Context; - -import org.apache.commons.io.FileUtils; -import org.sufficientlysecure.rootcommands.Shell; -import org.sufficientlysecure.rootcommands.Toolbox; - -import java.io.BufferedReader; -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; - - -public class RootUtils { - - public static void writeFile(Context context, String path, String text, String encoding, boolean isRoot) throws Exception { - File file = new File(path); - if (!file.canWrite() && isRoot) { - File appFolder = context.getFilesDir(); - File tempFile = new File(appFolder, "temp.root.file"); - if (!tempFile.exists()) - tempFile.createNewFile(); - FileUtils.write(tempFile, text, encoding); - Shell shell = Shell.startRootShell(); - Toolbox tb = new Toolbox(shell); - String mount = tb.getFilePermissions(path); - tb.copyFile(tempFile.getAbsolutePath(), path, true, false); - tb.setFilePermissions(path, mount); - tempFile.delete(); - } else { - FileUtils.write(file, - text, - encoding); - } - } - - public static ArrayList getFileList(String path, boolean runAtRoot) { - ArrayList filesList = new ArrayList(); - if (runAtRoot == false) { - File base = new File(path); - File[] files = base.listFiles(); - if (files == null) - return null; - Collections.addAll(filesList, files); - } else { - BufferedReader reader = null; //errReader = null; - try { - LinuxShell.execute("ls -a " + LinuxShell.getCommandLineString(path)); - if (reader == null) - return null; - - File f; - String line; - while ((line = reader.readLine()) != null) { - f = new File(line.substring(2)); - filesList.add(f); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - return filesList; - } - +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +/** + * 920 Text Editor 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. + * + * 920 Text Editor 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 920 Text Editor. If not, see . + */ + +package sharedcode.turboeditor.root; + +import android.content.Context; + +import org.apache.commons.io.FileUtils; +import org.sufficientlysecure.rootcommands.Shell; +import org.sufficientlysecure.rootcommands.Toolbox; + +import java.io.BufferedReader; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; + + +public class RootUtils { + + public static void writeFile(Context context, String path, String text, String encoding, boolean isRoot) throws Exception { + File file = new File(path); + if (!file.canWrite() && isRoot) { + File appFolder = context.getFilesDir(); + File tempFile = new File(appFolder, "temp.root.file"); + if (!tempFile.exists()) + tempFile.createNewFile(); + FileUtils.write(tempFile, text, encoding); + Shell shell = Shell.startRootShell(); + Toolbox tb = new Toolbox(shell); + String mount = tb.getFilePermissions(path); + tb.copyFile(tempFile.getAbsolutePath(), path, true, false); + tb.setFilePermissions(path, mount); + tempFile.delete(); + } else { + FileUtils.write(file, + text, + encoding); + } + } + + public static ArrayList getFileList(String path, boolean runAtRoot) { + ArrayList filesList = new ArrayList(); + if (runAtRoot == false) { + File base = new File(path); + File[] files = base.listFiles(); + if (files == null) + return null; + Collections.addAll(filesList, files); + } else { + BufferedReader reader = null; //errReader = null; + try { + LinuxShell.execute("ls -a " + LinuxShell.getCommandLineString(path)); + if (reader == null) + return null; + + File f; + String line; + while ((line = reader.readLine()) != null) { + f = new File(line.substring(2)); + filesList.add(f); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + return filesList; + } + } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/task/SaveFileTask.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/task/SaveFileTask.java index cc6284d..69b8bb2 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/task/SaveFileTask.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/task/SaveFileTask.java @@ -1,106 +1,106 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.task; - -import android.os.AsyncTask; -import android.widget.Toast; - -import org.sufficientlysecure.rootcommands.Shell; -import org.sufficientlysecure.rootcommands.Toolbox; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.activity.MainActivity; -import sharedcode.turboeditor.root.RootUtils; -import sharedcode.turboeditor.util.EventBusEvents; - -public class SaveFileTask extends AsyncTask { - - private final MainActivity activity; - private final String filePath; - private final String text; - private final String encoding; - private File file; - private String message; - private String positiveMessage; - - public SaveFileTask(MainActivity activity, String filePath, String text, String encoding) { - this.activity = activity; - this.filePath = filePath; - this.text = text; - this.encoding = encoding; - } - - @Override - protected void onPreExecute() { - super.onPreExecute(); - file = new File(filePath); - positiveMessage = String.format(activity.getString(R.string.file_saved_with_success), file.getName()); - } - - /** - * {@inheritDoc} - */ - @Override - protected Void doInBackground(final Void... voids) { - - try { - - if (!file.exists()) { - file.getParentFile().mkdirs(); - file.createNewFile(); - } - - boolean isRoot = false; - if (!file.canWrite()) { - try { - Shell shell = null; - shell = Shell.startRootShell(); - Toolbox tb = new Toolbox(shell); - isRoot = tb.isRootAccessGiven(); - } catch (IOException | TimeoutException e) { - e.printStackTrace(); - isRoot = false; - } - } - - RootUtils.writeFile(activity, file.getAbsolutePath(), text, encoding, isRoot); - - message = positiveMessage; - } catch (Exception e) { - message = e.getMessage(); - } - return null; - } - - /** - * {@inheritDoc} - */ - @Override - protected void onPostExecute(final Void aVoid) { - super.onPostExecute(aVoid); - Toast.makeText(activity, message, Toast.LENGTH_LONG).show(); - if (message.equals(positiveMessage)) - activity.onEvent(new EventBusEvents.SavedAFile(filePath)); - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.task; + +import android.os.AsyncTask; +import android.widget.Toast; + +import org.sufficientlysecure.rootcommands.Shell; +import org.sufficientlysecure.rootcommands.Toolbox; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.activity.MainActivity; +import sharedcode.turboeditor.root.RootUtils; +import sharedcode.turboeditor.util.EventBusEvents; + +public class SaveFileTask extends AsyncTask { + + private final MainActivity activity; + private final String filePath; + private final String text; + private final String encoding; + private File file; + private String message; + private String positiveMessage; + + public SaveFileTask(MainActivity activity, String filePath, String text, String encoding) { + this.activity = activity; + this.filePath = filePath; + this.text = text; + this.encoding = encoding; + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + file = new File(filePath); + positiveMessage = String.format(activity.getString(R.string.file_saved_with_success), file.getName()); + } + + /** + * {@inheritDoc} + */ + @Override + protected Void doInBackground(final Void... voids) { + + try { + + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + + boolean isRoot = false; + if (!file.canWrite()) { + try { + Shell shell = null; + shell = Shell.startRootShell(); + Toolbox tb = new Toolbox(shell); + isRoot = tb.isRootAccessGiven(); + } catch (IOException | TimeoutException e) { + e.printStackTrace(); + isRoot = false; + } + } + + RootUtils.writeFile(activity, file.getAbsolutePath(), text, encoding, isRoot); + + message = positiveMessage; + } catch (Exception e) { + message = e.getMessage(); + } + return null; + } + + /** + * {@inheritDoc} + */ + @Override + protected void onPostExecute(final Void aVoid) { + super.onPostExecute(aVoid); + Toast.makeText(activity, message, Toast.LENGTH_LONG).show(); + if (message.equals(positiveMessage)) + activity.onEvent(new EventBusEvents.SavedAFile(filePath)); + } } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/EditTextPadding.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/EditTextPadding.java index b378e7e..b5de286 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/EditTextPadding.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/EditTextPadding.java @@ -1,39 +1,39 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.texteditor; - -import android.content.Context; - -import sharedcode.turboeditor.util.PixelDipConverter; - -public class EditTextPadding { - - public static int getPaddingWithoutLineNumbers(Context context) { - return (int) PixelDipConverter.convertDpToPixel(5, context); - } - - public static int getPaddingWithLineNumbers(Context context, float fontSize) { - return (int) PixelDipConverter.convertDpToPixel(fontSize * 2f, context); - } - - public static int getPaddingTop(Context context) { - return getPaddingWithoutLineNumbers(context); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.texteditor; + +import android.content.Context; + +import sharedcode.turboeditor.util.PixelDipConverter; + +public class EditTextPadding { + + public static int getPaddingWithoutLineNumbers(Context context) { + return (int) PixelDipConverter.convertDpToPixel(5, context); + } + + public static int getPaddingWithLineNumbers(Context context, float fontSize) { + return (int) PixelDipConverter.convertDpToPixel(fontSize * 2f, context); + } + + public static int getPaddingTop(Context context) { + return getPaddingWithoutLineNumbers(context); + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/FileUtils.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/FileUtils.java index 5ad2a3e..54b3ccd 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/FileUtils.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/FileUtils.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.texteditor; - -import org.mozilla.universalchardet.UniversalDetector; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; - -public class FileUtils { - public static String getDetectedEncoding(File file) { - InputStream is = null; - String encoding = null; - try { - is = new FileInputStream(file); - UniversalDetector detector = new UniversalDetector(null); - byte[] buf = new byte[4096]; - int nread; - while ((nread = is.read(buf)) > 0 && !detector.isDone()) { - detector.handleData(buf, 0, nread); - } - detector.dataEnd(); - encoding = detector.getDetectedCharset(); - } catch (IOException e) { - // nothing to do - } finally { - try { - is.close(); - } catch (IOException e) { - e.printStackTrace(); - } - if (encoding == null) { - return Charset.defaultCharset().name(); - } - } - return encoding; - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.texteditor; + +import org.mozilla.universalchardet.UniversalDetector; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + +public class FileUtils { + public static String getDetectedEncoding(File file) { + InputStream is = null; + String encoding = null; + try { + is = new FileInputStream(file); + UniversalDetector detector = new UniversalDetector(null); + byte[] buf = new byte[4096]; + int nread; + while ((nread = is.read(buf)) > 0 && !detector.isDone()) { + detector.handleData(buf, 0, nread); + } + detector.dataEnd(); + encoding = detector.getDetectedCharset(); + } catch (IOException e) { + // nothing to do + } finally { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + if (encoding == null) { + return Charset.defaultCharset().name(); + } + } + return encoding; + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/LineUtils.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/LineUtils.java index 71b4b62..f6505ce 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/LineUtils.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/LineUtils.java @@ -1,133 +1,136 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.texteditor; - -import android.text.Layout; -import android.text.TextUtils; -import android.widget.ScrollView; - -public class LineUtils { - private boolean[] toCountLinesArray; - private int[] realLines; - - public boolean[] getToCountLinesArray() { - return toCountLinesArray; - } - - public int[] getRealLines() { - return realLines; - } - - public static int getYAtLine(ScrollView scrollView, int lineCount, int line) { - return scrollView.getChildAt(0).getHeight() / lineCount * line; - } - - public static int getFirstVisibleLine(ScrollView scrollView, int childHeight, int lineCount) throws ArithmeticException { - int line = (scrollView.getScrollY() * lineCount) / childHeight; - if (line < 0) line = 0; - return line; - } - - public static int getLastVisibleLine(ScrollView scrollView, int childHeight, int lineCount, int deviceHeight) { - int line = ((scrollView.getScrollY() + deviceHeight) * lineCount) / childHeight; - if (line > lineCount) line = lineCount; - return line; - } - - public void updateHasNewLineArray(int startingLine, int lineCount, Layout layout, String text) { - - boolean[] hasNewLineArray = new boolean[lineCount]; - toCountLinesArray = new boolean[lineCount]; - realLines = new int[lineCount]; - - if(TextUtils.isEmpty(text)) - return; - - int i; - - // for every line on the edittext - for (i = 0; i < lineCount; i++) { - // check if this line contains "\n" - //hasNewLineArray[i] = text.substring(layout.getLineStart(i), layout.getLineEnd(i)).endsWith("\n"); - hasNewLineArray[i] = text.charAt(layout.getLineEnd(i) - 1) == '\n'; - // if true - if (hasNewLineArray[i]) { - int j = i - 1; - while (j > -1 && !hasNewLineArray[j]) { - j--; - } - toCountLinesArray[j + 1] = true; - - } - } - - int realLine = startingLine; // the first line is not 0, is 1. We start counting from 1 - - for (i = 0; i < toCountLinesArray.length; i++) { - if (toCountLinesArray[i]) { - realLine++; - } - realLines[i] = realLine; - } - } - - /** - * Gets the line from the index of the letter in the text - * - * @param index - * @param lineCount - * @param layout - * @return - */ - public static int getLineFromIndex(int index, int lineCount, Layout layout) { - int line; - int currentIndex = 0; - - for (line = 0; line < lineCount; line++) { - currentIndex += layout.getLineEnd(line) - layout.getLineStart(line); - if (currentIndex > index) { - break; - } - } - - return line; - } - - public int firstReadLine() { - return realLines[0]; - } - - public int lastReadLine() { - return realLines[realLines.length - 1]; - } - - public int fakeLineFromRealLine(int realLine) { - int i; - int fakeLine = 0; - for (i = 0; i < realLines.length; i++) { - if (realLine == realLines[i]) { - fakeLine = i; - break; - } - } - return fakeLine; - } - +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.texteditor; + +import android.text.Layout; +import android.text.TextUtils; +import android.widget.ScrollView; + +public class LineUtils { + private boolean[] toCountLinesArray; + private int[] realLines; + + public boolean[] getToCountLinesArray() { + return toCountLinesArray; + } + + public int[] getRealLines() { + return realLines; + } + + public static int getYAtLine(ScrollView scrollView, int lineCount, int line) { + return scrollView.getChildAt(0).getHeight() / lineCount * line; + } + + public static int getFirstVisibleLine(ScrollView scrollView, int childHeight, int lineCount) throws ArithmeticException { + int line = (scrollView.getScrollY() * lineCount) / childHeight; + if (line < 0) line = 0; + return line; + } + + public static int getLastVisibleLine(ScrollView scrollView, int childHeight, int lineCount, int deviceHeight) { + int line = ((scrollView.getScrollY() + deviceHeight) * lineCount) / childHeight; + if (line > lineCount) line = lineCount; + return line; + } + + public void updateHasNewLineArray(int startingLine, int lineCount, Layout layout, String text) { + + boolean[] hasNewLineArray = new boolean[lineCount]; + toCountLinesArray = new boolean[lineCount]; + realLines = new int[lineCount]; + + if(TextUtils.isEmpty(text)) { + toCountLinesArray[0] = false; + realLines[0] = 1; + return; + } + + int i; + + // for every line on the edittext + for (i = 0; i < lineCount; i++) { + // check if this line contains "\n" + //hasNewLineArray[i] = text.substring(layout.getLineStart(i), layout.getLineEnd(i)).endsWith("\n"); + hasNewLineArray[i] = text.charAt(layout.getLineEnd(i) - 1) == '\n'; + // if true + if (hasNewLineArray[i]) { + int j = i - 1; + while (j > -1 && !hasNewLineArray[j]) { + j--; + } + toCountLinesArray[j + 1] = true; + + } + } + + int realLine = startingLine; // the first line is not 0, is 1. We start counting from 1 + + for (i = 0; i < toCountLinesArray.length; i++) { + if (toCountLinesArray[i]) { + realLine++; + } + realLines[i] = realLine; + } + } + + /** + * Gets the line from the index of the letter in the text + * + * @param index + * @param lineCount + * @param layout + * @return + */ + public static int getLineFromIndex(int index, int lineCount, Layout layout) { + int line; + int currentIndex = 0; + + for (line = 0; line < lineCount; line++) { + currentIndex += layout.getLineEnd(line) - layout.getLineStart(line); + if (currentIndex > index) { + break; + } + } + + return line; + } + + public int firstReadLine() { + return realLines[0]; + } + + public int lastReadLine() { + return realLines[realLines.length - 1]; + } + + public int fakeLineFromRealLine(int realLine) { + int i; + int fakeLine = 0; + for (i = 0; i < realLines.length; i++) { + if (realLine == realLines[i]) { + fakeLine = i; + break; + } + } + return fakeLine; + } + } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/PageSystem.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/PageSystem.java index 816ac99..6dc47cd 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/PageSystem.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/PageSystem.java @@ -1,183 +1,185 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.texteditor; - -import android.content.Context; -import android.support.annotation.Nullable; - -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.util.LinkedList; -import java.util.List; - -import sharedcode.turboeditor.preferences.PreferenceHelper; - -public class PageSystem { - - private List pages; - private int[] startingLines; - private int currentPage = 0; - private PageSystemInterface pageSystemInterface; - - public PageSystem(Context context, PageSystemInterface pageSystemInterface, String text, @Nullable File file) { - - final int charForPage = 15000; - final int MAX_KBs_WITHOUT_PAGE_SYSTEM = 50; - - this.pageSystemInterface = pageSystemInterface; - pages = new LinkedList<>(); - - final boolean dimensionOverLimit; - if(file != null && file.exists() && file.isFile()) - dimensionOverLimit = FileUtils.sizeOf(file) >= MAX_KBs_WITHOUT_PAGE_SYSTEM * FileUtils.ONE_KB; - else - dimensionOverLimit = false; - - int i = 0; - int to; - int nextIndexOfReturn; - final int textLength = text.length(); - boolean pageSystemEnabled = PreferenceHelper.getSplitText(context); - - if (pageSystemEnabled && dimensionOverLimit) { - while (i < textLength) { - to = i + charForPage; - nextIndexOfReturn = text.indexOf("\n", to); - if (nextIndexOfReturn > to) to = nextIndexOfReturn; - if (to > text.length()) to = text.length(); - pages.add(text.substring(i, to)); - i = to + 1; - } - - - if (i == 0) - pages.add(""); - } else { - pages.add(text); - } - - startingLines = new int[pages.size()]; - setStartingLines(); - } - - public int getStartingLine() { - return startingLines[currentPage]; - } - - public String getCurrentPageText() { - return pages.get(currentPage); - } - - public String getTextOfNextPages(boolean includeCurrent, int nOfPages) { - StringBuilder stringBuilder = new StringBuilder(); - int i; - for (i = includeCurrent ? 0 : 1; i < nOfPages; i++) { - if (pages.size() > (currentPage + i)) { - stringBuilder.append(pages.get(currentPage + 1)); - } - } - - return stringBuilder.toString(); - } - - public void savePage(String currentText) { - pages.set(currentPage, currentText); - } - - public void nextPage() { - if (!canReadNextPage()) return; - goToPage(currentPage + 1); - } - - public void prevPage() { - if (!canReadPrevPage()) return; - goToPage(currentPage - 1); - } - - public void goToPage(int page) { - if (page >= pages.size()) page = pages.size() - 1; - if (page < 0) page = 0; - boolean shouldUpdateLines = page > currentPage && canReadNextPage(); - if (shouldUpdateLines) { - String text = getCurrentPageText(); - int nOfNewLineNow = (text.length() - text.replace("\n", "").length()) + 1; // normally the last line is not counted so we have to add 1 - int nOfNewLineBefore = startingLines[currentPage + 1] - startingLines[currentPage]; - int difference = nOfNewLineNow - nOfNewLineBefore; - updateStartingLines(currentPage + 1, difference); - } - currentPage = page; - pageSystemInterface.onPageChanged(page); - } - - public void setStartingLines() { - int i; - int startingLine; - int nOfNewLines; - String text; - startingLines[0] = 0; - for (i = 1; i < pages.size(); i++) { - text = pages.get(i - 1); - nOfNewLines = text.length() - text.replace("\n", "").length() + 1; - startingLine = startingLines[i - 1] + nOfNewLines; - startingLines[i] = startingLine; - } - } - - public void updateStartingLines(int fromPage, int difference) { - if (difference == 0) - return; - int i; - if (fromPage < 1) fromPage = 1; - for (i = fromPage; i < pages.size(); i++) { - startingLines[i] += difference; - } - } - - public int getMaxPage() { - return pages.size() - 1; - } - - public int getCurrentPage() { - return currentPage; - } - - public String getAllText(String currentPageText) { - pages.set(currentPage, currentPageText); - int i; - StringBuilder allText = new StringBuilder(); - for (i = 0; i < pages.size(); i++) { - allText.append(pages.get(i)).append("\n"); - } - return allText.toString(); - } - - public boolean canReadNextPage() { - return currentPage < pages.size() - 1; - } - - public boolean canReadPrevPage() { - return currentPage >= 1; - } - - public interface PageSystemInterface { - void onPageChanged(int page); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.texteditor; + +import android.content.Context; +import android.support.annotation.Nullable; + +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.LinkedList; +import java.util.List; + +import sharedcode.turboeditor.preferences.PreferenceHelper; + +public class PageSystem { + + private List pages; + private int[] startingLines; + private int currentPage = 0; + private PageSystemInterface pageSystemInterface; + + public PageSystem(Context context, PageSystemInterface pageSystemInterface, String text, @Nullable File file) { + + final int charForPage = 15000; + final int MAX_KBs_WITHOUT_PAGE_SYSTEM = 50; + + this.pageSystemInterface = pageSystemInterface; + pages = new LinkedList<>(); + + final boolean dimensionOverLimit; + if(file != null && file.exists() && file.isFile()) + dimensionOverLimit = FileUtils.sizeOf(file) >= MAX_KBs_WITHOUT_PAGE_SYSTEM * FileUtils.ONE_KB; + else + dimensionOverLimit = false; + + int i = 0; + int to; + int nextIndexOfReturn; + final int textLength = text.length(); + boolean pageSystemEnabled = PreferenceHelper.getSplitText(context); + + if (pageSystemEnabled && dimensionOverLimit) { + while (i < textLength) { + to = i + charForPage; + nextIndexOfReturn = text.indexOf("\n", to); + if (nextIndexOfReturn > to) to = nextIndexOfReturn; + if (to > text.length()) to = text.length(); + pages.add(text.substring(i, to)); + i = to + 1; + } + + + if (i == 0) + pages.add(""); + } else { + pages.add(text); + } + + startingLines = new int[pages.size()]; + setStartingLines(); + } + + public int getStartingLine() { + return startingLines[currentPage]; + } + + public String getCurrentPageText() { + return pages.get(currentPage); + } + + public String getTextOfNextPages(boolean includeCurrent, int nOfPages) { + StringBuilder stringBuilder = new StringBuilder(); + int i; + for (i = includeCurrent ? 0 : 1; i < nOfPages; i++) { + if (pages.size() > (currentPage + i)) { + stringBuilder.append(pages.get(currentPage + 1)); + } + } + + return stringBuilder.toString(); + } + + public void savePage(String currentText) { + pages.set(currentPage, currentText); + } + + public void nextPage() { + if (!canReadNextPage()) return; + goToPage(currentPage + 1); + } + + public void prevPage() { + if (!canReadPrevPage()) return; + goToPage(currentPage - 1); + } + + public void goToPage(int page) { + if (page >= pages.size()) page = pages.size() - 1; + if (page < 0) page = 0; + boolean shouldUpdateLines = page > currentPage && canReadNextPage(); + if (shouldUpdateLines) { + String text = getCurrentPageText(); + int nOfNewLineNow = (text.length() - text.replace("\n", "").length()) + 1; // normally the last line is not counted so we have to add 1 + int nOfNewLineBefore = startingLines[currentPage + 1] - startingLines[currentPage]; + int difference = nOfNewLineNow - nOfNewLineBefore; + updateStartingLines(currentPage + 1, difference); + } + currentPage = page; + pageSystemInterface.onPageChanged(page); + } + + public void setStartingLines() { + int i; + int startingLine; + int nOfNewLines; + String text; + startingLines[0] = 0; + for (i = 1; i < pages.size(); i++) { + text = pages.get(i - 1); + nOfNewLines = text.length() - text.replace("\n", "").length() + 1; + startingLine = startingLines[i - 1] + nOfNewLines; + startingLines[i] = startingLine; + } + } + + public void updateStartingLines(int fromPage, int difference) { + if (difference == 0) + return; + int i; + if (fromPage < 1) fromPage = 1; + for (i = fromPage; i < pages.size(); i++) { + startingLines[i] += difference; + } + } + + public int getMaxPage() { + return pages.size() - 1; + } + + public int getCurrentPage() { + return currentPage; + } + + public String getAllText(String currentPageText) { + pages.set(currentPage, currentPageText); + int i; + StringBuilder allText = new StringBuilder(); + for (i = 0; i < pages.size(); i++) { + allText.append(pages.get(i)); + if(i < pages.size() - 1) + allText.append("\n"); + } + return allText.toString(); + } + + public boolean canReadNextPage() { + return currentPage < pages.size() - 1; + } + + public boolean canReadPrevPage() { + return currentPage >= 1; + } + + public interface PageSystemInterface { + void onPageChanged(int page); + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/PageSystemButtons.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/PageSystemButtons.java index 0f6a50e..3afe57b 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/PageSystemButtons.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/PageSystemButtons.java @@ -1,134 +1,134 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.texteditor; - -import android.content.Context; -import android.os.Handler; -import android.view.View; - -import com.faizmalkani.floatingactionbutton.FloatingActionButton; - -import sharedcode.turboeditor.R; - -public class PageSystemButtons { - - private static final int TIME_TO_SHOW_FABS = 2000; - final Handler handler = new Handler(); - final Runnable runnable = new Runnable() { - @Override - public void run() { - PageSystemButtons.this.next.setVisibility(View.GONE); - PageSystemButtons.this.prev.setVisibility(View.GONE); - } - }; - FloatingActionButton prev, next; - PageButtonsInterface pageButtonsInterface; - - public PageSystemButtons(Context context, final PageButtonsInterface pageButtonsInterface, FloatingActionButton prev, FloatingActionButton next) { - this.prev = prev; - this.next = next; - this.pageButtonsInterface = pageButtonsInterface; - - this.next.setColor(context.getResources().getColor(R.color.fab_light)); - this.next.setDrawable(context.getResources().getDrawable(R.drawable.ic_keyboard_arrow_right)); - - this.prev.setColor(context.getResources().getColor(R.color.fab_light)); - this.prev.setDrawable(context.getResources().getDrawable(R.drawable.ic_keyboard_arrow_left)); - - if (pageButtonsInterface.canReadNextPage()) - next.setVisibility(View.VISIBLE); - - if (pageButtonsInterface.canReadPrevPage()) - prev.setVisibility(View.VISIBLE); - - this.next.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - pageButtonsInterface.nextPageClicked(); - } - }); - - this.next.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - pageButtonsInterface.pageSystemButtonLongClicked(); - return true; - } - }); - - this.prev.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - pageButtonsInterface.prevPageClicked(); - } - }); - - this.prev.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - pageButtonsInterface.pageSystemButtonLongClicked(); - return true; - } - }); - } - - public void updateVisibility(boolean autoHide) { - - if (pageButtonsInterface.canReadNextPage()) - PageSystemButtons.this.next.setVisibility(View.VISIBLE); - else - PageSystemButtons.this.next.setVisibility(View.GONE); - - if (pageButtonsInterface.canReadPrevPage()) - PageSystemButtons.this.prev.setVisibility(View.VISIBLE); - else - PageSystemButtons.this.prev.setVisibility(View.GONE); - - /*if(pageButtonsInterface.hasNext()) - next.showFab(); - else - next.hideFab(); - - if(pageButtonsInterface.hasPrev()) - prev.showFab(); - else - prev.hideFab();*/ - - if (autoHide) { - handler.removeCallbacks(runnable); - handler.postDelayed(runnable, TIME_TO_SHOW_FABS); - } else { - handler.removeCallbacks(runnable); - } - } - - public interface PageButtonsInterface { - public void nextPageClicked(); - - public void prevPageClicked(); - - public void pageSystemButtonLongClicked(); - - public boolean canReadNextPage(); - - public boolean canReadPrevPage(); - } - -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.texteditor; + +import android.content.Context; +import android.os.Handler; +import android.view.View; + +import com.faizmalkani.floatingactionbutton.FloatingActionButton; + +import sharedcode.turboeditor.R; + +public class PageSystemButtons { + + private static final int TIME_TO_SHOW_FABS = 2000; + final Handler handler = new Handler(); + final Runnable runnable = new Runnable() { + @Override + public void run() { + PageSystemButtons.this.next.setVisibility(View.GONE); + PageSystemButtons.this.prev.setVisibility(View.GONE); + } + }; + FloatingActionButton prev, next; + PageButtonsInterface pageButtonsInterface; + + public PageSystemButtons(Context context, final PageButtonsInterface pageButtonsInterface, FloatingActionButton prev, FloatingActionButton next) { + this.prev = prev; + this.next = next; + this.pageButtonsInterface = pageButtonsInterface; + + this.next.setColor(context.getResources().getColor(R.color.fab_light)); + this.next.setDrawable(context.getResources().getDrawable(R.drawable.ic_keyboard_arrow_right)); + + this.prev.setColor(context.getResources().getColor(R.color.fab_light)); + this.prev.setDrawable(context.getResources().getDrawable(R.drawable.ic_keyboard_arrow_left)); + + if (pageButtonsInterface.canReadNextPage()) + next.setVisibility(View.VISIBLE); + + if (pageButtonsInterface.canReadPrevPage()) + prev.setVisibility(View.VISIBLE); + + this.next.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + pageButtonsInterface.nextPageClicked(); + } + }); + + this.next.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + pageButtonsInterface.pageSystemButtonLongClicked(); + return true; + } + }); + + this.prev.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + pageButtonsInterface.prevPageClicked(); + } + }); + + this.prev.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + pageButtonsInterface.pageSystemButtonLongClicked(); + return true; + } + }); + } + + public void updateVisibility(boolean autoHide) { + + if (pageButtonsInterface.canReadNextPage()) + PageSystemButtons.this.next.setVisibility(View.VISIBLE); + else + PageSystemButtons.this.next.setVisibility(View.GONE); + + if (pageButtonsInterface.canReadPrevPage()) + PageSystemButtons.this.prev.setVisibility(View.VISIBLE); + else + PageSystemButtons.this.prev.setVisibility(View.GONE); + + /*if(pageButtonsInterface.hasNext()) + next.showFab(); + else + next.hideFab(); + + if(pageButtonsInterface.hasPrev()) + prev.showFab(); + else + prev.hideFab();*/ + + if (autoHide) { + handler.removeCallbacks(runnable); + handler.postDelayed(runnable, TIME_TO_SHOW_FABS); + } else { + handler.removeCallbacks(runnable); + } + } + + public interface PageButtonsInterface { + public void nextPageClicked(); + + public void prevPageClicked(); + + public void pageSystemButtonLongClicked(); + + public boolean canReadNextPage(); + + public boolean canReadPrevPage(); + } + +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/Patterns.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/Patterns.java index 59b0462..483fb96 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/Patterns.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/Patterns.java @@ -1,92 +1,92 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.texteditor; - -import java.util.regex.Pattern; - -public class Patterns { - - /* - public static final int COLOR_NUMBER = 0xffff6600; - public static final int COLOR_KEYWORD = 0xff2f6f9f; - public static final int COLOR_ATTR = 0xff4f9fcf; - public static final int COLOR_ATTR_VALUE = 0xffd44950; - public static final int COLOR_STRING = 0xffd44950; - public static final int COLOR_COMMENT = 0xff999999; - */ - - // Strings - public static final Pattern GENERAL_STRINGS = Pattern.compile("\"(.*?)\"|'(.*?)'"); - - public static final Pattern HTML_OPEN_TAGS = Pattern.compile( - "<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>"); - public static final Pattern HTML_CLOSE_TAGS = Pattern.compile( - "]*>"); - public static final Pattern HTML_ATTRS = Pattern.compile( - "(\\S+)=[\"']?((?:.(?![\"']?\\s+(?:\\S+)=|[>\"']))+.)[\"']?"); - - //static final Pattern CSS_STYLE_NAME= Pattern.compile( - // "[ \\t\\n\\r\\f](.+?)\\{([^\\)]+)\\}"); - public static final Pattern CSS_ATTRS = Pattern.compile( - "(.+?):(.+?);"); - public static final Pattern CSS_ATTR_VALUE = Pattern.compile( - ":[ \t](.+?);"); - - public static final Pattern NUMBERS = Pattern.compile( - "(\\b(\\d*[.]?\\d+)\\b)"); - //public static final Pattern CSS_NUMBERS = Pattern.compile( - // "/^auto$|^[+-]?[0-9]+\\.?([0-9]+)?(px|em|ex|%|in|cm|mm|pt|pc)?$/ig"); - public static final Pattern SYMBOLS = Pattern.compile( - "(!|,|\\(|\\)|\\+|\\-|\\*|<|>|=|\\.|\\?|;|\\{|\\}|\\[|\\])"); - public static final Pattern NUMBERS_OR_SYMBOLS = Pattern.compile(NUMBERS.pattern()+"|"+SYMBOLS.pattern()); - public static final Pattern GENERAL_KEYWORDS = Pattern.compile( - "\\b(alignas|alignof|and|and_eq|asm|auto|bitand|bitorbool|break|case|catch|char|" - + "char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype" - + "|default|delete|do|double|dynamic_cast|echo|else|enum|explicit|export|extern|" - + "false|float|for|friend|function|goto|if|inline|int|mutable|namespace|new|noexcept|" - + "not|not_eq|null|nullptr|operator|or|or_eq|private|protected|public|register|" - + "reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast" - + "|struct|switch|template|this|thread_local|throw|true|try|typedef|typeid|typename|undefined" - + "|union|unsigned|using|var|virtual|void|volatile|wchar_t|while|xor|xor_eq|)\\b", Pattern.CASE_INSENSITIVE); - - public static final Pattern PY_KEYWORDS = Pattern.compile( - "\\b(int|float|long|complex|str|unicode|list|tuple|bytearray|buffer|xrange|set|frozenset|dict|bool)|(True|False|None|self|NotImplemented|Ellipsis|__debug__|__file__)|(and|del|from|not|while|as|elif|global|or|with|assert|else|if|pass|yield|break|except|import|print|class|exec|in|raise|continue|finally|is|return|def|for|lambda|try)|(ArithmeticError|AssertionError|AttributeError|BaseException|DeprecationWarning|EnvironmentError|EOFError|Exception|FloatingPointError|FutureWarning|GeneratorExit|IOError|ImportError|ImportWarning|IndexError|KeyError|KeyboardInterrupt|LookupError|MemoryError|NameError|NotImplementedError|OSError|OverflowError|PendingDeprecationWarning|ReferenceError|RuntimeError|RuntimeWarning|StandardError|StopIteration|SyntaxError|SyntaxWarning|SystemError|SystemExit|TypeError|UnboundLocalError|UserWarning|UnicodeError|UnicodeWarning|UnicodeEncodeError|UnicodeDecodeError|UnicodeTranslateError|ValueError|Warning|WindowsError|ZeroDivisionError)\\b", Pattern.CASE_INSENSITIVE); - - public static final Pattern LUA_KEYWORDS = Pattern.compile( - "@[A-Za-z0-9_\\.]*|\\b(local|global|boolean|number|userdata)\\b|\\b(true|false|nil)\\b|\\b(return|then|while|and|break|do|else|elseif|end|for|function|if|in|not|or|repeat|until|thread|table)\\b" + - "|(?i)\\b(editsetText|editText|inkey|touch|system.exit|system.expCall|system.getAppPath|system.getCardMnt|system.getSec|system.impCallActionSend|system.impCallActionView|system.setrun|system.setScreen|system.version|El_Psy_Congroo|canvas.drawCircle|canvas.drawCls|canvas.drawLine|canvas.drawRect|canvas.getBmpSize|canvas.getColor|canvas.getg|canvas.getviewSize|canvas.loadBmp|canvas.putCircle|canvas.putCls|canvas.putflush|canvas.putg|canvas.putLine|canvas.putRect|canvas.putrotg|canvas.putWork|canvas.saveBmp|canvas.setMainBmp|canvas.setWorkBmp|canvas.workCls|canvas.workflush|color|canvas.drawText|canvas.drawTextBox|canvas.drawTextCenter|canvas.drawTextRotate|canvas.putText|canvas.putTextBox|canvas.putTextRotate|http.addHeader|http.addParam|http.clrHeader|http.clrParam|http.get|http.post|http.setContentType|http.setPostFile|http.status|dialog|item.add|item.check|item.clear|item.list|item.radio|toast|sensor.getAccel|sensor.setdevAccel|sensor.setdevMagnet|sensor.setdevOrient|sensor.getGdirection|sensor.getMagnet|sensor.getOrient|sound.beep|sound.isPlay|sound.pause|sound.restart|sound.setSoundFile|sound.start|sound.stop|zip.addFile|zip.exec|zip.status|sock.close|sock.connectOpen|sock.getAddress|sock.listenOpen|sock.recv|sock.send|sprite.clear|sprite.define|sprite.init|sprite.move|sprite.put)\\b" + - "|(?i)\\b(assert|collectgarbage|coroutine.create|coroutine.resume|coroutine.running|coroutine.status|coroutine.wrap|coroutine.yield|debug.debug|debug.getfenv|debug.gethook|debug.getinfo|debug.getlocal|debug.getmetatable|debug.getregistry|debug.getupvalue|debug.setfenv|debug.sethook|debug.setlocal|debug.setmetatable|debug.setupvalue|debug.traceback|dofile|error|file:close|file:flush|file:lines|file:read|file:seek|file:setvbuf|file:write|getfenv|getmetatable|io.close|io.flush|io.input|io.lines|io.open|io.output|io.popen|io.read|io.tmpfile|io.type|io.write|ipairs|load|loadfile|loadstring|math.abs|math.acos|math.asin|math.atan2|math.atan|math.ceil|math.cosh|math.cos|math.deg|math.exp|math.floor|math.fmod|math.frexp|math.ldexp|math.log10|math.log|math.max|math.min|math.modf|math.pow|math.rad|math.random|math.randomseed|math.sinh|math.sin|math.sqrt|math.tanh|math.tan|module|next|os.clock|os.date|os.difftime|os.execute|os.exit|os.getenv|os.remove|os.rename|os.setlocale|os.time|os.tmpname|package.cpath|package.loaded|package.loadlib|package.path|package.preload|package.seeal|pairs|pcall|print|rawequal|rawget|rawset|require|select|setfenv|setmetatable|string.byte|string.char|string.dump|string.find|string.format|string.gmatch|string.gsub|string.len|string.lower|string.match|string.rep|string.reverse|string.sub|string.upper|table.concat|table.insert|table.maxn|table.remove|table.sort|tonumber|tostring|type|unpack|xpcall)\\b" - ); - - public static final Pattern PHP_VARIABLES = Pattern.compile("\\$\\s*(\\w+)"); - // Comments - public static final Pattern XML_COMMENTS = Pattern.compile("(?s)"); - public static final Pattern GENERAL_COMMENTS = Pattern.compile( - "/\\*(?:.|[\\n\\r])*?\\*/|(? // - public static final Pattern GENERAL_COMMENTS_NO_SLASH = Pattern.compile( - "/\\*(?:.|[\\n\\r])*?\\*/|#.*"); - public static final Pattern SQL_KEYWORDS = Pattern.compile( - "\\b(ADD|EXCEPT|PERCENT|ALL|EXEC|PLAN|ALTER|EXECUTE|PRECISION|AND|EXISTS|PRIMARY|ANY|EXIT|PRINT|AS|FETCH|PROC|ASC|FILE|PROCEDURE|AUTHORIZATION|FILLFACTOR|PUBLIC|BACKUP|FOR|RAISERROR|BEGIN|FOREIGN|READ|BETWEEN|FREETEXT|READTEXT|BREAK|FREETEXTTABLE|RECONFIGURE|BROWSE|FROM|REFERENCES|BULK|FULL|REPLICATION|BY|FUNCTION|RESTORE|CASCADE|GOTO|RESTRICT|CASE|GRANT|RETURN|CHECK|GROUP|REVOKE|CHECKPOINT|HAVING|RIGHT|CLOSE|HOLDLOCK|ROLLBACK|CLUSTERED|IDENTITY|ROWCOUNT|COALESCE|IDENTITY_INSERT|ROWGUIDCOL|COLLATE|IDENTITYCOL|RULE|COLUMN|IF|SAVE|COMMIT|IN|SCHEMA|COMPUTE|INDEX|SELECT|CONSTRAINT|INNER|SESSION_USER|CONTAINS|INSERT|SET|CONTAINSTABLE|INTERSECT|SETUSER|CONTINUE|INTO|SHUTDOWN|CONVERT|IS|SOME|CREATE|JOIN|STATISTICS|CROSS|KEY|SYSTEM_USER|CURRENT|KILL|TABLE|CURRENT_DATE|LEFT|TEXTSIZE|CURRENT_TIME|LIKE|THEN|CURRENT_TIMESTAMP|LINENO|TO|CURRENT_USER|LOAD|TOP|CURSOR|NATIONAL|TRAN|DATABASE|NOCHECK|TRANSACTION|DBCC|NONCLUSTERED|TRIGGER|DEALLOCATE|NOT|TRUNCATE|DECLARE|NULL|TSEQUAL|DEFAULT|NULLIF|UNION|DELETE|OF|UNIQUE|DENY|OFF|UPDATE|DESC|OFFSETS|UPDATETEXT|DISK|ON|USE|DISTINCT|OPEN|USER|DISTRIBUTED|OPENDATASOURCE|VALUES|DOUBLE|OPENQUERY|VARYING|DROP|OPENROWSET|VIEW|DUMMY|OPENXML|WAITFOR|DUMP|OPTION|WHEN|ELSE|OR|WHERE|END|ORDER|WHILE|ERRLVL|OUTER|WITH|ESCAPE|OVER|WRITETEXT)\\b", Pattern.CASE_INSENSITIVE); - - - public static final Pattern LINK = android.util.Patterns.WEB_URL; - -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.texteditor; + +import java.util.regex.Pattern; + +public class Patterns { + + /* + public static final int COLOR_NUMBER = 0xffff6600; + public static final int COLOR_KEYWORD = 0xff2f6f9f; + public static final int COLOR_ATTR = 0xff4f9fcf; + public static final int COLOR_ATTR_VALUE = 0xffd44950; + public static final int COLOR_STRING = 0xffd44950; + public static final int COLOR_COMMENT = 0xff999999; + */ + + // Strings + public static final Pattern GENERAL_STRINGS = Pattern.compile("\"(.*?)\"|'(.*?)'"); + + public static final Pattern HTML_OPEN_TAGS = Pattern.compile( + "<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>"); + public static final Pattern HTML_CLOSE_TAGS = Pattern.compile( + "]*>"); + public static final Pattern HTML_ATTRS = Pattern.compile( + "(\\S+)=[\"']?((?:.(?![\"']?\\s+(?:\\S+)=|[>\"']))+.)[\"']?"); + + //static final Pattern CSS_STYLE_NAME= Pattern.compile( + // "[ \\t\\n\\r\\f](.+?)\\{([^\\)]+)\\}"); + public static final Pattern CSS_ATTRS = Pattern.compile( + "(.+?):(.+?);"); + public static final Pattern CSS_ATTR_VALUE = Pattern.compile( + ":[ \t](.+?);"); + + public static final Pattern NUMBERS = Pattern.compile( + "(\\b(\\d*[.]?\\d+)\\b)"); + //public static final Pattern CSS_NUMBERS = Pattern.compile( + // "/^auto$|^[+-]?[0-9]+\\.?([0-9]+)?(px|em|ex|%|in|cm|mm|pt|pc)?$/ig"); + public static final Pattern SYMBOLS = Pattern.compile( + "(!|,|\\(|\\)|\\+|\\-|\\*|<|>|=|\\.|\\?|;|\\{|\\}|\\[|\\])"); + public static final Pattern NUMBERS_OR_SYMBOLS = Pattern.compile(NUMBERS.pattern()+"|"+SYMBOLS.pattern()); + public static final Pattern GENERAL_KEYWORDS = Pattern.compile( + "\\b(alignas|alignof|and|and_eq|asm|auto|bitand|bitorbool|break|case|catch|char|" + + "char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype" + + "|default|delete|do|double|dynamic_cast|echo|else|enum|explicit|export|extern|" + + "false|float|for|friend|function|goto|if|inline|int|mutable|namespace|new|noexcept|" + + "not|not_eq|null|nullptr|operator|or|or_eq|private|protected|public|register|" + + "reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast" + + "|struct|switch|template|this|thread_local|throw|true|try|typedef|typeid|typename|undefined" + + "|union|unsigned|using|var|virtual|void|volatile|wchar_t|while|xor|xor_eq|)\\b", Pattern.CASE_INSENSITIVE); + + public static final Pattern PY_KEYWORDS = Pattern.compile( + "\\b(int|float|long|complex|str|unicode|list|tuple|bytearray|buffer|xrange|set|frozenset|dict|bool)|(True|False|None|self|NotImplemented|Ellipsis|__debug__|__file__)|(and|del|from|not|while|as|elif|global|or|with|assert|else|if|pass|yield|break|except|import|print|class|exec|in|raise|continue|finally|is|return|def|for|lambda|try)|(ArithmeticError|AssertionError|AttributeError|BaseException|DeprecationWarning|EnvironmentError|EOFError|Exception|FloatingPointError|FutureWarning|GeneratorExit|IOError|ImportError|ImportWarning|IndexError|KeyError|KeyboardInterrupt|LookupError|MemoryError|NameError|NotImplementedError|OSError|OverflowError|PendingDeprecationWarning|ReferenceError|RuntimeError|RuntimeWarning|StandardError|StopIteration|SyntaxError|SyntaxWarning|SystemError|SystemExit|TypeError|UnboundLocalError|UserWarning|UnicodeError|UnicodeWarning|UnicodeEncodeError|UnicodeDecodeError|UnicodeTranslateError|ValueError|Warning|WindowsError|ZeroDivisionError)\\b", Pattern.CASE_INSENSITIVE); + + public static final Pattern LUA_KEYWORDS = Pattern.compile( + "@[A-Za-z0-9_\\.]*|\\b(local|global|boolean|number|userdata)\\b|\\b(true|false|nil)\\b|\\b(return|then|while|and|break|do|else|elseif|end|for|function|if|in|not|or|repeat|until|thread|table)\\b" + + "|(?i)\\b(editsetText|editText|inkey|touch|system.exit|system.expCall|system.getAppPath|system.getCardMnt|system.getSec|system.impCallActionSend|system.impCallActionView|system.setrun|system.setScreen|system.version|El_Psy_Congroo|canvas.drawCircle|canvas.drawCls|canvas.drawLine|canvas.drawRect|canvas.getBmpSize|canvas.getColor|canvas.getg|canvas.getviewSize|canvas.loadBmp|canvas.putCircle|canvas.putCls|canvas.putflush|canvas.putg|canvas.putLine|canvas.putRect|canvas.putrotg|canvas.putWork|canvas.saveBmp|canvas.setMainBmp|canvas.setWorkBmp|canvas.workCls|canvas.workflush|color|canvas.drawText|canvas.drawTextBox|canvas.drawTextCenter|canvas.drawTextRotate|canvas.putText|canvas.putTextBox|canvas.putTextRotate|http.addHeader|http.addParam|http.clrHeader|http.clrParam|http.get|http.post|http.setContentType|http.setPostFile|http.status|dialog|item.add|item.check|item.clear|item.list|item.radio|toast|sensor.getAccel|sensor.setdevAccel|sensor.setdevMagnet|sensor.setdevOrient|sensor.getGdirection|sensor.getMagnet|sensor.getOrient|sound.beep|sound.isPlay|sound.pause|sound.restart|sound.setSoundFile|sound.start|sound.stop|zip.addFile|zip.exec|zip.status|sock.close|sock.connectOpen|sock.getAddress|sock.listenOpen|sock.recv|sock.send|sprite.clear|sprite.define|sprite.init|sprite.move|sprite.put)\\b" + + "|(?i)\\b(assert|collectgarbage|coroutine.create|coroutine.resume|coroutine.running|coroutine.status|coroutine.wrap|coroutine.yield|debug.debug|debug.getfenv|debug.gethook|debug.getinfo|debug.getlocal|debug.getmetatable|debug.getregistry|debug.getupvalue|debug.setfenv|debug.sethook|debug.setlocal|debug.setmetatable|debug.setupvalue|debug.traceback|dofile|error|file:close|file:flush|file:lines|file:read|file:seek|file:setvbuf|file:write|getfenv|getmetatable|io.close|io.flush|io.input|io.lines|io.open|io.output|io.popen|io.read|io.tmpfile|io.type|io.write|ipairs|load|loadfile|loadstring|math.abs|math.acos|math.asin|math.atan2|math.atan|math.ceil|math.cosh|math.cos|math.deg|math.exp|math.floor|math.fmod|math.frexp|math.ldexp|math.log10|math.log|math.max|math.min|math.modf|math.pow|math.rad|math.random|math.randomseed|math.sinh|math.sin|math.sqrt|math.tanh|math.tan|module|next|os.clock|os.date|os.difftime|os.execute|os.exit|os.getenv|os.remove|os.rename|os.setlocale|os.time|os.tmpname|package.cpath|package.loaded|package.loadlib|package.path|package.preload|package.seeal|pairs|pcall|print|rawequal|rawget|rawset|require|select|setfenv|setmetatable|string.byte|string.char|string.dump|string.find|string.format|string.gmatch|string.gsub|string.len|string.lower|string.match|string.rep|string.reverse|string.sub|string.upper|table.concat|table.insert|table.maxn|table.remove|table.sort|tonumber|tostring|type|unpack|xpcall)\\b" + ); + + public static final Pattern PHP_VARIABLES = Pattern.compile("\\$\\s*(\\w+)"); + // Comments + public static final Pattern XML_COMMENTS = Pattern.compile("(?s)"); + public static final Pattern GENERAL_COMMENTS = Pattern.compile( + "/\\*(?:.|[\\n\\r])*?\\*/|(? // + public static final Pattern GENERAL_COMMENTS_NO_SLASH = Pattern.compile( + "/\\*(?:.|[\\n\\r])*?\\*/|#.*"); + public static final Pattern SQL_KEYWORDS = Pattern.compile( + "\\b(ADD|EXCEPT|PERCENT|ALL|EXEC|PLAN|ALTER|EXECUTE|PRECISION|AND|EXISTS|PRIMARY|ANY|EXIT|PRINT|AS|FETCH|PROC|ASC|FILE|PROCEDURE|AUTHORIZATION|FILLFACTOR|PUBLIC|BACKUP|FOR|RAISERROR|BEGIN|FOREIGN|READ|BETWEEN|FREETEXT|READTEXT|BREAK|FREETEXTTABLE|RECONFIGURE|BROWSE|FROM|REFERENCES|BULK|FULL|REPLICATION|BY|FUNCTION|RESTORE|CASCADE|GOTO|RESTRICT|CASE|GRANT|RETURN|CHECK|GROUP|REVOKE|CHECKPOINT|HAVING|RIGHT|CLOSE|HOLDLOCK|ROLLBACK|CLUSTERED|IDENTITY|ROWCOUNT|COALESCE|IDENTITY_INSERT|ROWGUIDCOL|COLLATE|IDENTITYCOL|RULE|COLUMN|IF|SAVE|COMMIT|IN|SCHEMA|COMPUTE|INDEX|SELECT|CONSTRAINT|INNER|SESSION_USER|CONTAINS|INSERT|SET|CONTAINSTABLE|INTERSECT|SETUSER|CONTINUE|INTO|SHUTDOWN|CONVERT|IS|SOME|CREATE|JOIN|STATISTICS|CROSS|KEY|SYSTEM_USER|CURRENT|KILL|TABLE|CURRENT_DATE|LEFT|TEXTSIZE|CURRENT_TIME|LIKE|THEN|CURRENT_TIMESTAMP|LINENO|TO|CURRENT_USER|LOAD|TOP|CURSOR|NATIONAL|TRAN|DATABASE|NOCHECK|TRANSACTION|DBCC|NONCLUSTERED|TRIGGER|DEALLOCATE|NOT|TRUNCATE|DECLARE|NULL|TSEQUAL|DEFAULT|NULLIF|UNION|DELETE|OF|UNIQUE|DENY|OFF|UPDATE|DESC|OFFSETS|UPDATETEXT|DISK|ON|USE|DISTINCT|OPEN|USER|DISTRIBUTED|OPENDATASOURCE|VALUES|DOUBLE|OPENQUERY|VARYING|DROP|OPENROWSET|VIEW|DUMMY|OPENXML|WAITFOR|DUMP|OPTION|WHEN|ELSE|OR|WHERE|END|ORDER|WHILE|ERRLVL|OUTER|WITH|ESCAPE|OVER|WRITETEXT)\\b", Pattern.CASE_INSENSITIVE); + + + public static final Pattern LINK = android.util.Patterns.WEB_URL; + +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/SearchResult.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/SearchResult.java index 5991dc9..1105101 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/SearchResult.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/SearchResult.java @@ -1,63 +1,63 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.texteditor; - -import java.util.LinkedList; - -public class SearchResult { - // list of index - public LinkedList foundIndex; - public int textLength; - public boolean isReplace; - public String textToReplace; - public int index; - - public SearchResult(LinkedList foundIndex, int textLength, boolean isReplace, String textToReplace) { - this.foundIndex = foundIndex; - this.textLength = textLength; - this.isReplace = isReplace; - this.textToReplace = textToReplace; - } - - public void doneReplace() { - foundIndex.remove(index); - int i; - for (i = index; i < foundIndex.size(); i++) { - foundIndex.set(i, foundIndex.get(i) + textToReplace.length() - textLength); - } - index--; // an element was removed so we decrease the index - } - - public int numberOfResults() { - return foundIndex.size(); - } - - public boolean hasNext() { - return index < foundIndex.size() - 1; - } - - public boolean hasPrevious() { - return index > 0; - } - - public boolean canReplaceSomething() { - return isReplace && foundIndex.size() > 0; - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.texteditor; + +import java.util.LinkedList; + +public class SearchResult { + // list of index + public LinkedList foundIndex; + public int textLength; + public boolean isReplace; + public String textToReplace; + public int index; + + public SearchResult(LinkedList foundIndex, int textLength, boolean isReplace, String textToReplace) { + this.foundIndex = foundIndex; + this.textLength = textLength; + this.isReplace = isReplace; + this.textToReplace = textToReplace; + } + + public void doneReplace() { + foundIndex.remove(index); + int i; + for (i = index; i < foundIndex.size(); i++) { + foundIndex.set(i, foundIndex.get(i) + textToReplace.length() - textLength); + } + index--; // an element was removed so we decrease the index + } + + public int numberOfResults() { + return foundIndex.size(); + } + + public boolean hasNext() { + return index < foundIndex.size() - 1; + } + + public boolean hasPrevious() { + return index > 0; + } + + public boolean canReplaceSomething() { + return isReplace && foundIndex.size() > 0; + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AccessStorageApi.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AccessStorageApi.java index cadedd9..a9d3bed 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AccessStorageApi.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AccessStorageApi.java @@ -1,208 +1,208 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util; - -import android.annotation.SuppressLint; -import android.content.ContentUris; -import android.content.Context; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -public class AccessStorageApi { - - public static Bitmap loadPrescaledBitmap(String filename) throws IOException { - // Facebook image size - final int IMAGE_MAX_SIZE = 630; - - File file = null; - FileInputStream fis; - - BitmapFactory.Options opts; - int resizeScale; - Bitmap bmp; - - file = new File(filename); - - // This bit determines only the width/height of the bitmap without loading the contents - opts = new BitmapFactory.Options(); - opts.inJustDecodeBounds = true; - fis = new FileInputStream(file); - BitmapFactory.decodeStream(fis, null, opts); - fis.close(); - - // Find the correct scale value. It should be a power of 2 - resizeScale = 1; - - if (opts.outHeight > IMAGE_MAX_SIZE || opts.outWidth > IMAGE_MAX_SIZE) { - resizeScale = (int) Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(opts.outHeight, opts.outWidth)) / Math.log(0.5))); - } - - // Load pre-scaled bitmap - opts = new BitmapFactory.Options(); - opts.inSampleSize = resizeScale; - fis = new FileInputStream(file); - bmp = BitmapFactory.decodeStream(fis, null, opts); - - fis.close(); - - return bmp; - } - - /** - * Get a file path from a Uri. This will get the the path for Storage Access - * Framework Documents, as well as the _data field for the MediaStore and - * other file-based ContentProviders. - * - * @param context The context. - * @param uri The Uri to query. - * @author paulburke - */ - @SuppressLint("NewApi") - public static String getPath(final Context context, final Uri uri) { - - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - - // DocumentProvider - if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { - // ExternalStorageProvider - if (isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - return Environment.getExternalStorageDirectory() + "/" + split[1]; - } - - // TODO handle non-primary volumes - } - // DownloadsProvider - else if (isDownloadsDocument(uri)) { - - final String id = DocumentsContract.getDocumentId(uri); - final Uri contentUri = ContentUris.withAppendedId( - Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); - - return getDataColumn(context, contentUri, null, null); - } - // MediaProvider - else if (isMediaDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = "_id=?"; - final String[] selectionArgs = new String[]{ - split[1] - }; - - return getDataColumn(context, contentUri, selection, selectionArgs); - } - } - // MediaStore (and general) - else if ("content".equalsIgnoreCase(uri.getScheme())) { - return getDataColumn(context, uri, null, null); - } - // File - else if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); - } - - return null; - } - - /** - * Get the value of the data column for this Uri. This is useful for - * MediaStore Uris, and other file-based ContentProviders. - * - * @param context The context. - * @param uri The Uri to query. - * @param selection (Optional) Filter used in the query. - * @param selectionArgs (Optional) Selection arguments used in the query. - * @return The value of the _data column, which is typically a file path. - */ - public static String getDataColumn(Context context, Uri uri, String selection, - String[] selectionArgs) { - - Cursor cursor = null; - final String column = "_data"; - final String[] projection = { - column - }; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, - null); - if (cursor != null && cursor.moveToFirst()) { - final int column_index = cursor.getColumnIndexOrThrow(column); - return cursor.getString(column_index); - } - } finally { - if (cursor != null) - cursor.close(); - } - return null; - } - - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is ExternalStorageProvider. - */ - public static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is DownloadsProvider. - */ - public static boolean isDownloadsDocument(Uri uri) { - return "com.android.providers.downloads.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is MediaProvider. - */ - public static boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } - -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util; + +import android.annotation.SuppressLint; +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +public class AccessStorageApi { + + public static Bitmap loadPrescaledBitmap(String filename) throws IOException { + // Facebook image size + final int IMAGE_MAX_SIZE = 630; + + File file = null; + FileInputStream fis; + + BitmapFactory.Options opts; + int resizeScale; + Bitmap bmp; + + file = new File(filename); + + // This bit determines only the width/height of the bitmap without loading the contents + opts = new BitmapFactory.Options(); + opts.inJustDecodeBounds = true; + fis = new FileInputStream(file); + BitmapFactory.decodeStream(fis, null, opts); + fis.close(); + + // Find the correct scale value. It should be a power of 2 + resizeScale = 1; + + if (opts.outHeight > IMAGE_MAX_SIZE || opts.outWidth > IMAGE_MAX_SIZE) { + resizeScale = (int) Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(opts.outHeight, opts.outWidth)) / Math.log(0.5))); + } + + // Load pre-scaled bitmap + opts = new BitmapFactory.Options(); + opts.inSampleSize = resizeScale; + fis = new FileInputStream(file); + bmp = BitmapFactory.decodeStream(fis, null, opts); + + fis.close(); + + return bmp; + } + + /** + * Get a file path from a Uri. This will get the the path for Storage Access + * Framework Documents, as well as the _data field for the MediaStore and + * other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @author paulburke + */ + @SuppressLint("NewApi") + public static String getPath(final Context context, final Uri uri) { + + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + // DocumentProvider + if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { + // ExternalStorageProvider + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + + // TODO handle non-primary volumes + } + // DownloadsProvider + else if (isDownloadsDocument(uri)) { + + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris.withAppendedId( + Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + + return getDataColumn(context, contentUri, null, null); + } + // MediaProvider + else if (isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[]{ + split[1] + }; + + return getDataColumn(context, contentUri, selection, selectionArgs); + } + } + // MediaStore (and general) + else if ("content".equalsIgnoreCase(uri.getScheme())) { + return getDataColumn(context, uri, null, null); + } + // File + else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + + return null; + } + + /** + * Get the value of the data column for this Uri. This is useful for + * MediaStore Uris, and other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @param selection (Optional) Filter used in the query. + * @param selectionArgs (Optional) Selection arguments used in the query. + * @return The value of the _data column, which is typically a file path. + */ + public static String getDataColumn(Context context, Uri uri, String selection, + String[] selectionArgs) { + + Cursor cursor = null; + final String column = "_data"; + final String[] projection = { + column + }; + + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, + null); + if (cursor != null && cursor.moveToFirst()) { + final int column_index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(column_index); + } + } finally { + if (cursor != null) + cursor.close(); + } + return null; + } + + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + */ + public static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + */ + public static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + */ + public static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AlphanumComparator.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AlphanumComparator.java index 0911107..98b5990 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AlphanumComparator.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AlphanumComparator.java @@ -1,138 +1,138 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util;/* - * The Alphanum Algorithm is an improved sorting algorithm for strings - * containing numbers. Instead of sorting numbers in ASCII order like - * a standard sort, this algorithm sorts numbers in numeric order. - * - * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -import java.util.Comparator; - -/** - * This is an updated version with enhancements made by Daniel Migowski, Andre Bogus, and David - * Koelle - *

- * To convert to use Templates (Java 1.5+): - Change "implements Comparator" to "implements - * Comparator" - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)" - - * Remove the type checking and casting in compare(). - *

- * To use this class: Use the static "sort" method from the java.util.Collections class: - * Collections.sort(your list, new AlphanumComparator()); - */ -public class AlphanumComparator implements Comparator { - private boolean isDigit(char ch) { - return ch >= 48 && ch <= 57; - } - - /** - * Length of string is passed in for improved efficiency (only need to calculate it once) * - */ - private String getChunk(String s, int slength, int marker) { - StringBuilder chunk = new StringBuilder(); - char c = s.charAt(marker); - chunk.append(c); - marker++; - if (isDigit(c)) { - while (marker < slength) { - c = s.charAt(marker); - if (!isDigit(c)) { - break; - } - chunk.append(c); - marker++; - } - } else { - while (marker < slength) { - c = s.charAt(marker); - if (isDigit(c)) { - break; - } - chunk.append(c); - marker++; - } - } - return chunk.toString(); - } - - public String getTheString(Object obj) { - return (String) obj; - } - - public int compare(Object o1, Object o2) { - String s1 = getTheString(o1); - String s2 = getTheString(o2); - - int thisMarker = 0; - int thatMarker = 0; - int s1Length = s1.length(); - int s2Length = s2.length(); - - while (thisMarker < s1Length && thatMarker < s2Length) { - String thisChunk = getChunk(s1, s1Length, thisMarker); - thisMarker += thisChunk.length(); - - String thatChunk = getChunk(s2, s2Length, thatMarker); - thatMarker += thatChunk.length(); - - // If both chunks contain numeric characters, sort them numerically - int result = 0; - if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) { - // Simple chunk comparison by length. - int thisChunkLength = thisChunk.length(); - result = thisChunkLength - thatChunk.length(); - // If equal, the first different number counts - if (result == 0) { - for (int i = 0; i < thisChunkLength; i++) { - result = thisChunk.charAt(i) - thatChunk.charAt(i); - if (result != 0) { - return result; - } - } - } - } else { - result = thisChunk.compareTo(thatChunk); - } - - if (result != 0) { - return result; - } - } - - return s1Length - s2Length; - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util;/* + * The Alphanum Algorithm is an improved sorting algorithm for strings + * containing numbers. Instead of sorting numbers in ASCII order like + * a standard sort, this algorithm sorts numbers in numeric order. + * + * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +import java.util.Comparator; + +/** + * This is an updated version with enhancements made by Daniel Migowski, Andre Bogus, and David + * Koelle + *

+ * To convert to use Templates (Java 1.5+): - Change "implements Comparator" to "implements + * Comparator" - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)" - + * Remove the type checking and casting in compare(). + *

+ * To use this class: Use the static "sort" method from the java.util.Collections class: + * Collections.sort(your list, new AlphanumComparator()); + */ +public class AlphanumComparator implements Comparator { + private boolean isDigit(char ch) { + return ch >= 48 && ch <= 57; + } + + /** + * Length of string is passed in for improved efficiency (only need to calculate it once) * + */ + private String getChunk(String s, int slength, int marker) { + StringBuilder chunk = new StringBuilder(); + char c = s.charAt(marker); + chunk.append(c); + marker++; + if (isDigit(c)) { + while (marker < slength) { + c = s.charAt(marker); + if (!isDigit(c)) { + break; + } + chunk.append(c); + marker++; + } + } else { + while (marker < slength) { + c = s.charAt(marker); + if (isDigit(c)) { + break; + } + chunk.append(c); + marker++; + } + } + return chunk.toString(); + } + + public String getTheString(Object obj) { + return (String) obj; + } + + public int compare(Object o1, Object o2) { + String s1 = getTheString(o1); + String s2 = getTheString(o2); + + int thisMarker = 0; + int thatMarker = 0; + int s1Length = s1.length(); + int s2Length = s2.length(); + + while (thisMarker < s1Length && thatMarker < s2Length) { + String thisChunk = getChunk(s1, s1Length, thisMarker); + thisMarker += thisChunk.length(); + + String thatChunk = getChunk(s2, s2Length, thatMarker); + thatMarker += thatChunk.length(); + + // If both chunks contain numeric characters, sort them numerically + int result = 0; + if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) { + // Simple chunk comparison by length. + int thisChunkLength = thisChunk.length(); + result = thisChunkLength - thatChunk.length(); + // If equal, the first different number counts + if (result == 0) { + for (int i = 0; i < thisChunkLength; i++) { + result = thisChunk.charAt(i) - thatChunk.charAt(i); + if (result != 0) { + return result; + } + } + } + } else { + result = thisChunk.compareTo(thatChunk); + } + + if (result != 0) { + return result; + } + } + + return s1Length - s2Length; + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AnimationUtils.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AnimationUtils.java index f89bb6b..54904e9 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AnimationUtils.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AnimationUtils.java @@ -1,52 +1,52 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.ActivityOptionsCompat; -import android.view.View; - -public class AnimationUtils { - public static Bundle getScaleBundle(View view) { - return ActivityOptionsCompat.makeScaleUpAnimation( - view, 0, 0, view.getWidth(), view.getHeight()).toBundle(); - } - - public static void startActivityWithScale(@NonNull Activity startActivity, @NonNull Intent subActivity, @NonNull boolean forResult, @Nullable int code, @NonNull View view) { - if(forResult){ - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) - startActivity.startActivityForResult(subActivity, code, AnimationUtils.getScaleBundle - (view)); - else - startActivity.startActivityForResult(subActivity, code); - } - else { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) - startActivity.startActivity(subActivity, AnimationUtils.getScaleBundle - (view)); - else - startActivity.startActivity(subActivity); - } - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.ActivityOptionsCompat; +import android.view.View; + +public class AnimationUtils { + public static Bundle getScaleBundle(View view) { + return ActivityOptionsCompat.makeScaleUpAnimation( + view, 0, 0, view.getWidth(), view.getHeight()).toBundle(); + } + + public static void startActivityWithScale(@NonNull Activity startActivity, @NonNull Intent subActivity, @NonNull boolean forResult, @Nullable int code, @NonNull View view) { + if(forResult){ + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) + startActivity.startActivityForResult(subActivity, code, AnimationUtils.getScaleBundle + (view)); + else + startActivity.startActivityForResult(subActivity, code); + } + else { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) + startActivity.startActivity(subActivity, AnimationUtils.getScaleBundle + (view)); + else + startActivity.startActivity(subActivity); + } + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AppInfoHelper.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AppInfoHelper.java index d0379ca..6855bcb 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AppInfoHelper.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/AppInfoHelper.java @@ -1,42 +1,42 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; - -public class AppInfoHelper { - public static String getApplicationName(final Context context) { - final ApplicationInfo applicationInfo = context.getApplicationInfo(); - return context.getString(applicationInfo.labelRes); - } - - public static String getCurrentVersion(final Context context) { - try { - final PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), - 0); - return packageInfo.versionName; - } catch (PackageManager.NameNotFoundException e) { - return ""; - } - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; + +public class AppInfoHelper { + public static String getApplicationName(final Context context) { + final ApplicationInfo applicationInfo = context.getApplicationInfo(); + return context.getString(applicationInfo.labelRes); + } + + public static String getCurrentVersion(final Context context) { + try { + final PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), + 0); + return packageInfo.versionName; + } catch (PackageManager.NameNotFoundException e) { + return ""; + } + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/EventBusEvents.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/EventBusEvents.java index 916ea51..9505a42 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/EventBusEvents.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/EventBusEvents.java @@ -1,115 +1,115 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util; - -import java.io.File; -import java.util.List; - -public class EventBusEvents { - public static class CannotOpenAFile { - - } - - public static class NewFileToOpen { - - private final File file; - private final String fileText; - - public NewFileToOpen(File file) { - this.file = file; - this.fileText = ""; - } - - public NewFileToOpen(String fileText) { - this.file = new File(""); - this.fileText = fileText; - } - - public File getFile() { - return file; - } - - public String getFileText() { - return fileText; - } - } - - public static class AFileIsSelected { - - private final String path; - - public AFileIsSelected(String path) { - this.path = path; - } - - public String getPath() { - return path; - } - } - - public static class APreferenceValueWasChanged { - private Type type; - private List types; - - public APreferenceValueWasChanged(Type type) { - this.type = type; - } - - public APreferenceValueWasChanged(List types) { - this.types = types; - } - - public boolean hasType(Type value) { - - if (type != null) { - return value == type; - } else { - return types.contains(value); - } - - } - - public enum Type { - FONT_SIZE, ENCODING, SYNTAX, WRAP_CONTENT, MONOSPACE, LINE_NUMERS, THEME_CHANGE, TEXT_SUGGESTIONS, READ_ONLY, - } - } - - public static class SaveAFile { - } - - public static class SavedAFile { - private final String path; - - public SavedAFile(String path) { - this.path = path; - } - - public String getPath() { - return path; - } - } - - public static class ClosedAFile { - } - - public static class InvalideTheMenu { - } - -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util; + +import java.io.File; +import java.util.List; + +public class EventBusEvents { + public static class CannotOpenAFile { + + } + + public static class NewFileToOpen { + + private final File file; + private final String fileText; + + public NewFileToOpen(File file) { + this.file = file; + this.fileText = ""; + } + + public NewFileToOpen(String fileText) { + this.file = new File(""); + this.fileText = fileText; + } + + public File getFile() { + return file; + } + + public String getFileText() { + return fileText; + } + } + + public static class AFileIsSelected { + + private final String path; + + public AFileIsSelected(String path) { + this.path = path; + } + + public String getPath() { + return path; + } + } + + public static class APreferenceValueWasChanged { + private Type type; + private List types; + + public APreferenceValueWasChanged(Type type) { + this.type = type; + } + + public APreferenceValueWasChanged(List types) { + this.types = types; + } + + public boolean hasType(Type value) { + + if (type != null) { + return value == type; + } else { + return types.contains(value); + } + + } + + public enum Type { + FONT_SIZE, ENCODING, SYNTAX, WRAP_CONTENT, MONOSPACE, LINE_NUMERS, THEME_CHANGE, TEXT_SUGGESTIONS, READ_ONLY, + } + } + + public static class SaveAFile { + } + + public static class SavedAFile { + private final String path; + + public SavedAFile(String path) { + this.path = path; + } + + public String getPath() { + return path; + } + } + + public static class ClosedAFile { + } + + public static class InvalideTheMenu { + } + +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/IHomeActivity.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/IHomeActivity.java new file mode 100644 index 0000000..ec2c898 --- /dev/null +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/IHomeActivity.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util; + +public interface IHomeActivity { + public abstract boolean showInterstitial(); +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/MimeTypes.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/MimeTypes.java index bba14c1..39ec0f3 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/MimeTypes.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/MimeTypes.java @@ -1,57 +1,57 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util; - -public class MimeTypes { - public static final String[] MIME_TEXT = { - "ajx", "am", "asa", "asc", "asp", "aspx", "awk", "bat", "c", "cdf", "cf", "cfg", "cfm", "cgi", "cnf", "conf", - "cc", "cpp", "css", "csv", "ctl", "dat", "dhtml", "diz", "file", "forward", "grp", "h", "hh", "hpp", "hqx", "hta", "htaccess", - "htc", "htm", "html", "htpasswd", "htt", "htx", "in", "inc", "info", "ini", "ink", "java", "js", "jsp", "key", "latex", "log", - "logfile", "m3u", "m4", "m4a", "mak", "map", "md", "markdown", "model", "msg", "nfo", "nsi", "info", "old", "pas", "patch", "perl", - "php", "php2", "php3", "php4", "php5", "php6", "phtml", "pix", "pl", "pm", "po", "pwd", "py", "qmail", "rb", "rbl", "rbw", - "readme", "reg", "rss", "rtf", "ruby", "session", "setup", "sh", "shtm", "shtml", "sql", "ssh", "stm", "style", "svg", "tcl", - "tex", "text", "threads", "tmpl", "tpl", "txt", "ubb", "vbs", "xhtml", "xml", "xrc", "xsl" - }; - public static final String[] MIME_CODE = { - "cs", "php", "js", "java", "py", "rb", "aspx", "cshtml", "vbhtml", "go", "c", "h", "cc", "cpp", "hh", "hpp", "pl", "pm", "t", "pod", - "m", "f", "for", "f90", "f95", "asp", "json", "wiki", "lua", "r" - }; - public static final String[] MIME_HTML = { - "htm", "html", "xhtml" - }; - public static final String[] MIME_PICTURE = { - "bmp", "eps", "png", "jpeg", "jpg", "ico", "gif", "tiff", "webp" - }; - public static final String[] MIME_MUSIC = { - "aac", "flac", "mp3", "mpga", "oga", "ogg", "opus", "webma", "wav" - }; - public static final String[] MIME_VIDEO = { - "avi", "mp4", "mkv", "wmw", "ogv", "webm" - }; - public static final String[] MIME_ARCHIVE = { - "7z", "arj", "bz2", "gz", "rar", "tar", "tgz", "zip", "xz" - }; - public static final String[] MIME_SQL = { - "sql", "mdf", "ndf", "ldf" - }; - public static final String[] MIME_MARKDOWN = { - "md", "mdown", "markdown", - }; -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util; + +public class MimeTypes { + public static final String[] MIME_TEXT = { + "ajx", "am", "asa", "asc", "asp", "aspx", "awk", "bat", "c", "cdf", "cf", "cfg", "cfm", "cgi", "cnf", "conf", + "cc", "cpp", "css", "csv", "ctl", "dat", "dhtml", "diz", "file", "forward", "grp", "h", "hh", "hpp", "hqx", "hta", "htaccess", + "htc", "htm", "html", "htpasswd", "htt", "htx", "in", "inc", "info", "ini", "ink", "java", "js", "jsp", "key", "latex", "log", + "logfile", "m3u", "m4", "m4a", "mak", "map", "md", "markdown", "model", "msg", "nfo", "nsi", "info", "old", "pas", "patch", "perl", + "php", "php2", "php3", "php4", "php5", "php6", "phtml", "pix", "pl", "pm", "po", "pwd", "py", "qmail", "rb", "rbl", "rbw", + "readme", "reg", "rss", "rtf", "ruby", "session", "setup", "sh", "shtm", "shtml", "sql", "ssh", "stm", "style", "svg", "tcl", + "tex", "text", "threads", "tmpl", "tpl", "txt", "ubb", "vbs", "xhtml", "xml", "xrc", "xsl" + }; + public static final String[] MIME_CODE = { + "cs", "php", "js", "java", "py", "rb", "aspx", "cshtml", "vbhtml", "go", "c", "h", "cc", "cpp", "hh", "hpp", "pl", "pm", "t", "pod", + "m", "f", "for", "f90", "f95", "asp", "json", "wiki", "lua", "r" + }; + public static final String[] MIME_HTML = { + "htm", "html", "xhtml" + }; + public static final String[] MIME_PICTURE = { + "bmp", "eps", "png", "jpeg", "jpg", "ico", "gif", "tiff", "webp" + }; + public static final String[] MIME_MUSIC = { + "aac", "flac", "mp3", "mpga", "oga", "ogg", "opus", "webma", "wav" + }; + public static final String[] MIME_VIDEO = { + "avi", "mp4", "mkv", "wmw", "ogv", "webm" + }; + public static final String[] MIME_ARCHIVE = { + "7z", "arj", "bz2", "gz", "rar", "tar", "tgz", "zip", "xz" + }; + public static final String[] MIME_SQL = { + "sql", "mdf", "ndf", "ldf" + }; + public static final String[] MIME_MARKDOWN = { + "md", "mdown", "markdown", + }; +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/PixelDipConverter.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/PixelDipConverter.java index 1c50d0e..0b6cb1b 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/PixelDipConverter.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/PixelDipConverter.java @@ -1,56 +1,56 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util; - -import android.content.Context; -import android.content.res.Resources; -import android.util.DisplayMetrics; - -public final class PixelDipConverter { - - private PixelDipConverter() { - } - - /** - * This method convets dp unit to equivalent device specific value in pixels. - * - * @param dp A value in dp(Device independent pixels) unit. Which we need to convert into pixels - * @param context Context to get resources and device specific display metrics - * @return A float value to represent Pixels equivalent to dp according to device - */ - public static float convertDpToPixel(final float dp, final Context context) { - final Resources resources = context.getResources(); - final DisplayMetrics metrics = resources.getDisplayMetrics(); - return dp * metrics.densityDpi / 160f; - } - - /** - * This method converts device specific pixels to device independent pixels. - * - * @param px A value in px (pixels) unit. Which we need to convert into db - * @param context Context to get resources and device specific display metrics - * @return A float value to represent db equivalent to px value - */ - public static float convertPixelsToDp(final float px, final Context context) { - final Resources resources = context.getResources(); - final DisplayMetrics metrics = resources.getDisplayMetrics(); - return px / (metrics.densityDpi / 160f); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util; + +import android.content.Context; +import android.content.res.Resources; +import android.util.DisplayMetrics; + +public final class PixelDipConverter { + + private PixelDipConverter() { + } + + /** + * This method convets dp unit to equivalent device specific value in pixels. + * + * @param dp A value in dp(Device independent pixels) unit. Which we need to convert into pixels + * @param context Context to get resources and device specific display metrics + * @return A float value to represent Pixels equivalent to dp according to device + */ + public static float convertDpToPixel(final float dp, final Context context) { + final Resources resources = context.getResources(); + final DisplayMetrics metrics = resources.getDisplayMetrics(); + return dp * metrics.densityDpi / 160f; + } + + /** + * This method converts device specific pixels to device independent pixels. + * + * @param px A value in px (pixels) unit. Which we need to convert into db + * @param context Context to get resources and device specific display metrics + * @return A float value to represent db equivalent to px value + */ + public static float convertPixelsToDp(final float px, final Context context) { + final Resources resources = context.getResources(); + final DisplayMetrics metrics = resources.getDisplayMetrics(); + return px / (metrics.densityDpi / 160f); + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ProCheckUtils.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ProCheckUtils.java index f909309..c9af73c 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ProCheckUtils.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ProCheckUtils.java @@ -1,44 +1,44 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util; - -import android.content.Context; - -import sharedcode.turboeditor.preferences.PreferenceHelper; - -public class ProCheckUtils { - public static boolean isPro(Context context, boolean includeDonations) { - - String packageName = context.getPackageName(); - - if (Build.FOR_AMAZON) - return true; - else if (packageName.equals("com.maskyn.fileeditorpro")) - return true; - else if (includeDonations && PreferenceHelper.hasDonated(context)) - return true; - else - return false; - } - - public static boolean isPro(Context context) { - return isPro(context, true); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util; + +import android.content.Context; + +import sharedcode.turboeditor.preferences.PreferenceHelper; + +public class ProCheckUtils { + public static boolean isPro(Context context, boolean includeDonations) { + + String packageName = context.getPackageName(); + + if (Build.FOR_AMAZON) + return true; + else if (packageName.equals("com.maskyn.fileeditorpro")) + return true; + else if (includeDonations && PreferenceHelper.hasDonated(context)) + return true; + else + return false; + } + + public static boolean isPro(Context context) { + return isPro(context, true); + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ThemeUtils.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ThemeUtils.java index acbeb5d..d36899d 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ThemeUtils.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ThemeUtils.java @@ -1,55 +1,55 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util; - -import android.app.Activity; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.preferences.PreferenceHelper; - -public class ThemeUtils { - - public static void setTheme(Activity activity){ - boolean light = PreferenceHelper.getLightTheme(activity); - if (light) { - activity.setTheme(R.style.AppThemeBaseLight); - } else { - activity.setTheme(R.style.AppThemeBaseDark); - } - } - - public static void setPreferenceTheme(Activity activity){ - boolean light = PreferenceHelper.getLightTheme(activity); - if (light) { - activity.setTheme(R.style.PreferenceLight); - } else { - activity.setTheme(R.style.PreferenceDark); - } - } - - public static void setWindowsBackground(Activity activity) { - boolean whiteTheme = PreferenceHelper.getLightTheme(activity); - if (whiteTheme) { - activity.getWindow().setBackgroundDrawableResource(R.color.window_background_light); - } else { - activity.getWindow().setBackgroundDrawableResource(R.color.window_background); - } - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util; + +import android.app.Activity; + +import sharedcode.turboeditor.R; +import sharedcode.turboeditor.preferences.PreferenceHelper; + +public class ThemeUtils { + + public static void setTheme(Activity activity){ + boolean light = PreferenceHelper.getLightTheme(activity); + if (light) { + activity.setTheme(R.style.AppThemeBaseLight); + } else { + activity.setTheme(R.style.AppThemeBaseDark); + } + } + + public static void setPreferenceTheme(Activity activity){ + boolean light = PreferenceHelper.getLightTheme(activity); + if (light) { + activity.setTheme(R.style.PreferenceLight); + } else { + activity.setTheme(R.style.PreferenceDark); + } + } + + public static void setWindowsBackground(Activity activity) { + boolean whiteTheme = PreferenceHelper.getLightTheme(activity); + if (whiteTheme) { + activity.getWindow().setBackgroundDrawableResource(R.color.window_background_light); + } else { + activity.getWindow().setBackgroundDrawableResource(R.color.window_background); + } + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelper.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelper.java index dd5e419..5d83e98 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelper.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelper.java @@ -1,290 +1,290 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util.systemui; - -import android.app.Activity; -import android.os.Build; -import android.os.Handler; -import android.os.Looper; -import android.view.WindowManager; - -/** - * Helper for controlling the visibility of the System UI across the various API levels. To use - * this API, instantiate an instance of this class with the required level. The level specifies the - * extent to which the System UI's visibility is changed when you call {@link #hide()} - * or {@link #toggle()}. - */ -public final class SystemUiHelper { - - /** - * In this level, the helper will toggle low profile mode. - */ - public static final int LEVEL_LOW_PROFILE = 0; - - /** - * In this level, the helper will toggle the visibility of the status bar. - * If there is a navigation bar, it will toggle low profile mode. - */ - public static final int LEVEL_HIDE_STATUS_BAR = 1; - - /** - * In this level, the helper will toggle the visibility of the navigation bar - * (if present and if possible) and status bar. In cases where the navigation - * bar is present but cannot be hidden, it will toggle low profile mode. - */ - public static final int LEVEL_LEAN_BACK = 2; - - /** - * In this level, the helper will toggle the visibility of the navigation bar - * (if present and if possible) and status bar, in an immersive mode. This means that the app - * will continue to receive all touch events. The user can reveal the system bars with an - * inward swipe along the region where the system bars normally appear. - * - *

The {@link #FLAG_IMMERSIVE_STICKY} flag can be used to control how the system bars are - * displayed. - */ - public static final int LEVEL_IMMERSIVE = 3; - - /** - * When this flag is set, the - * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN} - * flag will be set on older devices, making the status bar "float" on top - * of the activity layout. This is most useful when there are no controls at - * the top of the activity layout. - *

- * This flag isn't used on newer devices because the action - * bar, the most important structural element of an Android app, should - * be visible and not obscured by the system UI. - */ - public static final int FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES = 0x1; - - /** - * Used with {@link #LEVEL_IMMERSIVE}. When this flag is set, an inward swipe in the system - * bars areas will cause the system bars to temporarily appear in a semi-transparent state, - * but no flags are cleared, and your system UI visibility change listeners are not triggered. - * The bars automatically hide again after a short delay, or if the user interacts with the - * middle of the screen. - */ - public static final int FLAG_IMMERSIVE_STICKY = 0x2; - - private static final String LOG_TAG = SystemUiHelper.class.getSimpleName(); - - private final SystemUiHelperImpl mImpl; - - private final Handler mHandler; - private final Runnable mHideRunnable; - - /** - * Construct a new SystemUiHelper. - * - * @param activity The Activity who's system UI should be changed - * @param level The level of hiding. Should be either {@link #LEVEL_LOW_PROFILE}, - * {@link #LEVEL_HIDE_STATUS_BAR}, {@link #LEVEL_LEAN_BACK} or - * {@link #LEVEL_IMMERSIVE} - * @param flags Additional options. See {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES} and - * {@link #FLAG_IMMERSIVE_STICKY} - */ - public SystemUiHelper(Activity activity, int level, int flags) { - this(activity, level, flags, null); - } - - /** - * Construct a new SystemUiHelper. - * - * @param activity The Activity who's system UI should be changed - * @param level The level of hiding. Should be either {@link #LEVEL_LOW_PROFILE}, - * {@link #LEVEL_HIDE_STATUS_BAR}, {@link #LEVEL_LEAN_BACK} or - * {@link #LEVEL_IMMERSIVE} - * @param flags Additional options. See {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES} and - * {@link #FLAG_IMMERSIVE_STICKY} - * @param listener A listener which is called when the system visibility is changed - */ - public SystemUiHelper(Activity activity, int level, int flags, - OnVisibilityChangeListener listener) { - - mHandler = new Handler(Looper.getMainLooper()); - mHideRunnable = new HideRunnable(); - - // Create impl - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - mImpl = new SystemUiHelperImplKK(activity, level, flags, listener); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - mImpl = new SystemUiHelperImplJB(activity, level, flags, listener); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - mImpl = new SystemUiHelperImplICS(activity, level, flags, listener); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - mImpl = new SystemUiHelperImplHC(activity, level, flags, listener); - } else { - mImpl = new SystemUiHelperImplBase(activity, level, flags, listener); - } - } - - /** - * @return true if the system UI is currently showing. What this means depends on the mode this - * {@link android.example.android.systemuivis.SystemUiHelper} was instantiated with. - */ - public boolean isShowing() { - return mImpl.isShowing(); - } - - /** - * Show the system UI. What this means depends on the mode this {@link android.example.android.systemuivis.SystemUiHelper} was - * instantiated with. - * - *

Any currently queued delayed hide requests will be removed. - */ - public void show() { - // Ensure that any currently queued hide calls are removed - removeQueuedRunnables(); - - mImpl.show(); - } - - /** - * Hide the system UI. What this means depends on the mode this {@link android.example.android.systemuivis.SystemUiHelper} was - * instantiated with. - * - *

Any currently queued delayed hide requests will be removed. - */ - public void hide() { - // Ensure that any currently queued hide calls are removed - removeQueuedRunnables(); - - mImpl.hide(); - } - - /** - * Request that the system UI is hidden after a delay. - * - *

Any currently queued delayed hide requests will be removed. - * - * @param delayMillis The delay (in milliseconds) until the Runnable - * will be executed. - */ - public void delayHide(long delayMillis) { - // Ensure that any currently queued hide calls are removed - removeQueuedRunnables(); - - mHandler.postDelayed(mHideRunnable, delayMillis); - } - - /** - * Toggle whether the system UI is displayed. - */ - public void toggle() { - if (mImpl.isShowing()) { - mImpl.hide(); - } else { - mImpl.show(); - } - } - - private void removeQueuedRunnables() { - // Ensure that any currently queued hide calls are removed - mHandler.removeCallbacks(mHideRunnable); - } - - /** - * A callback interface used to listen for system UI visibility changes. - */ - public interface OnVisibilityChangeListener { - /** - * Called when the system UI visibility has changed. - * - * @param visible True if the system UI is visible. - */ - public void onVisibilityChange(boolean visible); - } - - static abstract class SystemUiHelperImpl { - - final Activity mActivity; - final int mLevel; - final int mFlags; - final OnVisibilityChangeListener mOnVisibilityChangeListener; - - boolean mIsShowing = true; - - SystemUiHelperImpl(Activity activity, int level, int flags, - OnVisibilityChangeListener onVisibilityChangeListener) { - mActivity = activity; - mLevel = level; - mFlags = flags; - mOnVisibilityChangeListener = onVisibilityChangeListener; - } - - abstract void show(); - abstract void hide(); - - boolean isShowing() { - return mIsShowing; - } - - void setIsShowing(boolean isShowing) { - mIsShowing = isShowing; - - if (mOnVisibilityChangeListener != null) { - mOnVisibilityChangeListener.onVisibilityChange(mIsShowing); - } - } - } - - /** - * Base implementation. Used on API level 10 and below. - */ - static class SystemUiHelperImplBase extends SystemUiHelperImpl { - - SystemUiHelperImplBase(Activity activity, int level, int flags, - OnVisibilityChangeListener onVisibilityChangeListener) { - super(activity, level, flags, onVisibilityChangeListener); - - if ((mFlags & SystemUiHelper.FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES) != 0) { - mActivity.getWindow().addFlags( - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - } - } - - @Override - void show() { - if (mLevel > SystemUiHelper.LEVEL_LOW_PROFILE) { - mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - setIsShowing(true); - } - } - - @Override - void hide() { - if (mLevel > SystemUiHelper.LEVEL_LOW_PROFILE) { - mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - setIsShowing(false); - } - } - } - - private class HideRunnable implements Runnable { - @Override - public void run() { - hide(); - } - } - -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util.systemui; + +import android.app.Activity; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.view.WindowManager; + +/** + * Helper for controlling the visibility of the System UI across the various API levels. To use + * this API, instantiate an instance of this class with the required level. The level specifies the + * extent to which the System UI's visibility is changed when you call {@link #hide()} + * or {@link #toggle()}. + */ +public final class SystemUiHelper { + + /** + * In this level, the helper will toggle low profile mode. + */ + public static final int LEVEL_LOW_PROFILE = 0; + + /** + * In this level, the helper will toggle the visibility of the status bar. + * If there is a navigation bar, it will toggle low profile mode. + */ + public static final int LEVEL_HIDE_STATUS_BAR = 1; + + /** + * In this level, the helper will toggle the visibility of the navigation bar + * (if present and if possible) and status bar. In cases where the navigation + * bar is present but cannot be hidden, it will toggle low profile mode. + */ + public static final int LEVEL_LEAN_BACK = 2; + + /** + * In this level, the helper will toggle the visibility of the navigation bar + * (if present and if possible) and status bar, in an immersive mode. This means that the app + * will continue to receive all touch events. The user can reveal the system bars with an + * inward swipe along the region where the system bars normally appear. + * + *

The {@link #FLAG_IMMERSIVE_STICKY} flag can be used to control how the system bars are + * displayed. + */ + public static final int LEVEL_IMMERSIVE = 3; + + /** + * When this flag is set, the + * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN} + * flag will be set on older devices, making the status bar "float" on top + * of the activity layout. This is most useful when there are no controls at + * the top of the activity layout. + *

+ * This flag isn't used on newer devices because the action + * bar, the most important structural element of an Android app, should + * be visible and not obscured by the system UI. + */ + public static final int FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES = 0x1; + + /** + * Used with {@link #LEVEL_IMMERSIVE}. When this flag is set, an inward swipe in the system + * bars areas will cause the system bars to temporarily appear in a semi-transparent state, + * but no flags are cleared, and your system UI visibility change listeners are not triggered. + * The bars automatically hide again after a short delay, or if the user interacts with the + * middle of the screen. + */ + public static final int FLAG_IMMERSIVE_STICKY = 0x2; + + private static final String LOG_TAG = SystemUiHelper.class.getSimpleName(); + + private final SystemUiHelperImpl mImpl; + + private final Handler mHandler; + private final Runnable mHideRunnable; + + /** + * Construct a new SystemUiHelper. + * + * @param activity The Activity who's system UI should be changed + * @param level The level of hiding. Should be either {@link #LEVEL_LOW_PROFILE}, + * {@link #LEVEL_HIDE_STATUS_BAR}, {@link #LEVEL_LEAN_BACK} or + * {@link #LEVEL_IMMERSIVE} + * @param flags Additional options. See {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES} and + * {@link #FLAG_IMMERSIVE_STICKY} + */ + public SystemUiHelper(Activity activity, int level, int flags) { + this(activity, level, flags, null); + } + + /** + * Construct a new SystemUiHelper. + * + * @param activity The Activity who's system UI should be changed + * @param level The level of hiding. Should be either {@link #LEVEL_LOW_PROFILE}, + * {@link #LEVEL_HIDE_STATUS_BAR}, {@link #LEVEL_LEAN_BACK} or + * {@link #LEVEL_IMMERSIVE} + * @param flags Additional options. See {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES} and + * {@link #FLAG_IMMERSIVE_STICKY} + * @param listener A listener which is called when the system visibility is changed + */ + public SystemUiHelper(Activity activity, int level, int flags, + OnVisibilityChangeListener listener) { + + mHandler = new Handler(Looper.getMainLooper()); + mHideRunnable = new HideRunnable(); + + // Create impl + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + mImpl = new SystemUiHelperImplKK(activity, level, flags, listener); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + mImpl = new SystemUiHelperImplJB(activity, level, flags, listener); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + mImpl = new SystemUiHelperImplICS(activity, level, flags, listener); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mImpl = new SystemUiHelperImplHC(activity, level, flags, listener); + } else { + mImpl = new SystemUiHelperImplBase(activity, level, flags, listener); + } + } + + /** + * @return true if the system UI is currently showing. What this means depends on the mode this + * {@link android.example.android.systemuivis.SystemUiHelper} was instantiated with. + */ + public boolean isShowing() { + return mImpl.isShowing(); + } + + /** + * Show the system UI. What this means depends on the mode this {@link android.example.android.systemuivis.SystemUiHelper} was + * instantiated with. + * + *

Any currently queued delayed hide requests will be removed. + */ + public void show() { + // Ensure that any currently queued hide calls are removed + removeQueuedRunnables(); + + mImpl.show(); + } + + /** + * Hide the system UI. What this means depends on the mode this {@link android.example.android.systemuivis.SystemUiHelper} was + * instantiated with. + * + *

Any currently queued delayed hide requests will be removed. + */ + public void hide() { + // Ensure that any currently queued hide calls are removed + removeQueuedRunnables(); + + mImpl.hide(); + } + + /** + * Request that the system UI is hidden after a delay. + * + *

Any currently queued delayed hide requests will be removed. + * + * @param delayMillis The delay (in milliseconds) until the Runnable + * will be executed. + */ + public void delayHide(long delayMillis) { + // Ensure that any currently queued hide calls are removed + removeQueuedRunnables(); + + mHandler.postDelayed(mHideRunnable, delayMillis); + } + + /** + * Toggle whether the system UI is displayed. + */ + public void toggle() { + if (mImpl.isShowing()) { + mImpl.hide(); + } else { + mImpl.show(); + } + } + + private void removeQueuedRunnables() { + // Ensure that any currently queued hide calls are removed + mHandler.removeCallbacks(mHideRunnable); + } + + /** + * A callback interface used to listen for system UI visibility changes. + */ + public interface OnVisibilityChangeListener { + /** + * Called when the system UI visibility has changed. + * + * @param visible True if the system UI is visible. + */ + public void onVisibilityChange(boolean visible); + } + + static abstract class SystemUiHelperImpl { + + final Activity mActivity; + final int mLevel; + final int mFlags; + final OnVisibilityChangeListener mOnVisibilityChangeListener; + + boolean mIsShowing = true; + + SystemUiHelperImpl(Activity activity, int level, int flags, + OnVisibilityChangeListener onVisibilityChangeListener) { + mActivity = activity; + mLevel = level; + mFlags = flags; + mOnVisibilityChangeListener = onVisibilityChangeListener; + } + + abstract void show(); + abstract void hide(); + + boolean isShowing() { + return mIsShowing; + } + + void setIsShowing(boolean isShowing) { + mIsShowing = isShowing; + + if (mOnVisibilityChangeListener != null) { + mOnVisibilityChangeListener.onVisibilityChange(mIsShowing); + } + } + } + + /** + * Base implementation. Used on API level 10 and below. + */ + static class SystemUiHelperImplBase extends SystemUiHelperImpl { + + SystemUiHelperImplBase(Activity activity, int level, int flags, + OnVisibilityChangeListener onVisibilityChangeListener) { + super(activity, level, flags, onVisibilityChangeListener); + + if ((mFlags & SystemUiHelper.FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES) != 0) { + mActivity.getWindow().addFlags( + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + } + } + + @Override + void show() { + if (mLevel > SystemUiHelper.LEVEL_LOW_PROFILE) { + mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + setIsShowing(true); + } + } + + @Override + void hide() { + if (mLevel > SystemUiHelper.LEVEL_LOW_PROFILE) { + mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + setIsShowing(false); + } + } + } + + private class HideRunnable implements Runnable { + @Override + public void run() { + hide(); + } + } + +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplHC.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplHC.java index 431f6d8..9c62667 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplHC.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplHC.java @@ -1,94 +1,94 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util.systemui; - -import android.app.Activity; -import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; -import android.view.View; -import android.view.WindowManager; - -class SystemUiHelperImplHC extends SystemUiHelper.SystemUiHelperImpl - implements View.OnSystemUiVisibilityChangeListener { - - final View mDecorView; - - SystemUiHelperImplHC(Activity activity, int level, int flags, - SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) { - super(activity, level, flags, onVisibilityChangeListener); - - mDecorView = activity.getWindow().getDecorView(); - mDecorView.setOnSystemUiVisibilityChangeListener(this); - } - - - @Override - void show() { - mDecorView.setSystemUiVisibility(createShowFlags()); - } - - @Override - void hide() { - mDecorView.setSystemUiVisibility(createHideFlags()); - } - - @Override - public final void onSystemUiVisibilityChange(int visibility) { - if ((visibility & createTestFlags()) != 0) { - onSystemUiHidden(); - } else { - onSystemUiShown(); - } - } - - protected void onSystemUiShown() { - ActionBar ab = ((ActionBarActivity) mActivity).getSupportActionBar(); - if (ab != null) { - ab.show(); - } - - mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - - setIsShowing(true); - } - - protected void onSystemUiHidden() { - ActionBar ab = ((ActionBarActivity) mActivity).getSupportActionBar(); - if (ab != null) { - ab.hide(); - } - - mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - - setIsShowing(false); - } - - protected int createShowFlags() { - return View.STATUS_BAR_VISIBLE; - } - - protected int createHideFlags() { - return View.STATUS_BAR_HIDDEN; - } - - protected int createTestFlags() { - return View.STATUS_BAR_HIDDEN; - } +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util.systemui; + +import android.app.Activity; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.view.View; +import android.view.WindowManager; + +class SystemUiHelperImplHC extends SystemUiHelper.SystemUiHelperImpl + implements View.OnSystemUiVisibilityChangeListener { + + final View mDecorView; + + SystemUiHelperImplHC(Activity activity, int level, int flags, + SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) { + super(activity, level, flags, onVisibilityChangeListener); + + mDecorView = activity.getWindow().getDecorView(); + mDecorView.setOnSystemUiVisibilityChangeListener(this); + } + + + @Override + void show() { + mDecorView.setSystemUiVisibility(createShowFlags()); + } + + @Override + void hide() { + mDecorView.setSystemUiVisibility(createHideFlags()); + } + + @Override + public final void onSystemUiVisibilityChange(int visibility) { + if ((visibility & createTestFlags()) != 0) { + onSystemUiHidden(); + } else { + onSystemUiShown(); + } + } + + protected void onSystemUiShown() { + ActionBar ab = ((ActionBarActivity) mActivity).getSupportActionBar(); + if (ab != null) { + ab.show(); + } + + mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + + setIsShowing(true); + } + + protected void onSystemUiHidden() { + ActionBar ab = ((ActionBarActivity) mActivity).getSupportActionBar(); + if (ab != null) { + ab.hide(); + } + + mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + + setIsShowing(false); + } + + protected int createShowFlags() { + return View.STATUS_BAR_VISIBLE; + } + + protected int createHideFlags() { + return View.STATUS_BAR_HIDDEN; + } + + protected int createTestFlags() { + return View.STATUS_BAR_HIDDEN; + } } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplICS.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplICS.java index 11d5829..ece98f2 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplICS.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplICS.java @@ -1,60 +1,60 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util.systemui; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.os.Build; -import android.view.View; - -@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) -class SystemUiHelperImplICS extends SystemUiHelperImplHC { - - SystemUiHelperImplICS(Activity activity, int level, int flags, - SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) { - super(activity, level, flags, onVisibilityChangeListener); - } - - @Override - protected int createShowFlags() { - return View.SYSTEM_UI_FLAG_VISIBLE; - } - - @Override - protected int createTestFlags() { - if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) { - // Intentionally override test flags. - return View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - } - - return View.SYSTEM_UI_FLAG_LOW_PROFILE; - } - - @Override - protected int createHideFlags() { - int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE; - - if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) { - flag |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - } - - return flag; - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util.systemui; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.os.Build; +import android.view.View; + +@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) +class SystemUiHelperImplICS extends SystemUiHelperImplHC { + + SystemUiHelperImplICS(Activity activity, int level, int flags, + SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) { + super(activity, level, flags, onVisibilityChangeListener); + } + + @Override + protected int createShowFlags() { + return View.SYSTEM_UI_FLAG_VISIBLE; + } + + @Override + protected int createTestFlags() { + if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) { + // Intentionally override test flags. + return View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + } + + return View.SYSTEM_UI_FLAG_LOW_PROFILE; + } + + @Override + protected int createHideFlags() { + int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE; + + if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) { + flag |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + } + + return flag; + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplJB.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplJB.java index f19e7c7..34cd072 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplJB.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplJB.java @@ -1,93 +1,93 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util.systemui; - -import android.annotation.TargetApi; -import android.app.ActionBar; -import android.app.Activity; -import android.os.Build; -import android.view.View; - -@TargetApi(Build.VERSION_CODES.JELLY_BEAN) -class SystemUiHelperImplJB extends SystemUiHelperImplICS { - - SystemUiHelperImplJB(Activity activity, int level, int flags, - SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) { - super(activity, level, flags, onVisibilityChangeListener); - } - - @Override - protected int createShowFlags() { - int flag = super.createShowFlags(); - - if (mLevel >= SystemUiHelper.LEVEL_HIDE_STATUS_BAR) { - flag |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - - if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) { - flag |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; - } - } - - return flag; - } - - @Override - protected int createHideFlags() { - int flag = super.createHideFlags(); - - if (mLevel >= SystemUiHelper.LEVEL_HIDE_STATUS_BAR) { - flag |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_FULLSCREEN; - - if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) { - flag |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; - } - } - - return flag; - } - - @Override - protected void onSystemUiShown() { - if (mLevel == SystemUiHelper.LEVEL_LOW_PROFILE) { - // Manually show the action bar when in low profile mode. - ActionBar ab = mActivity.getActionBar(); - if (ab != null) { - ab.show(); - } - } - - setIsShowing(false); - } - - @Override - protected void onSystemUiHidden() { - if (mLevel == SystemUiHelper.LEVEL_LOW_PROFILE) { - // Manually hide the action bar when in low profile mode. - ActionBar ab = mActivity.getActionBar(); - if (ab != null) { - ab.hide(); - } - } - - setIsShowing(true); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util.systemui; + +import android.annotation.TargetApi; +import android.app.ActionBar; +import android.app.Activity; +import android.os.Build; +import android.view.View; + +@TargetApi(Build.VERSION_CODES.JELLY_BEAN) +class SystemUiHelperImplJB extends SystemUiHelperImplICS { + + SystemUiHelperImplJB(Activity activity, int level, int flags, + SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) { + super(activity, level, flags, onVisibilityChangeListener); + } + + @Override + protected int createShowFlags() { + int flag = super.createShowFlags(); + + if (mLevel >= SystemUiHelper.LEVEL_HIDE_STATUS_BAR) { + flag |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + + if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) { + flag |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + } + } + + return flag; + } + + @Override + protected int createHideFlags() { + int flag = super.createHideFlags(); + + if (mLevel >= SystemUiHelper.LEVEL_HIDE_STATUS_BAR) { + flag |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_FULLSCREEN; + + if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) { + flag |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + } + } + + return flag; + } + + @Override + protected void onSystemUiShown() { + if (mLevel == SystemUiHelper.LEVEL_LOW_PROFILE) { + // Manually show the action bar when in low profile mode. + ActionBar ab = mActivity.getActionBar(); + if (ab != null) { + ab.show(); + } + } + + setIsShowing(false); + } + + @Override + protected void onSystemUiHidden() { + if (mLevel == SystemUiHelper.LEVEL_LOW_PROFILE) { + // Manually hide the action bar when in low profile mode. + ActionBar ab = mActivity.getActionBar(); + if (ab != null) { + ab.hide(); + } + } + + setIsShowing(true); + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplKK.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplKK.java index 988fc46..8ad73ed 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplKK.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/systemui/SystemUiHelperImplKK.java @@ -1,53 +1,53 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.util.systemui; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.os.Build; -import android.view.View; - -@TargetApi(Build.VERSION_CODES.KITKAT) -class SystemUiHelperImplKK extends SystemUiHelperImplJB { - - SystemUiHelperImplKK(Activity activity, int level, int flags, - SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) { - super(activity, level, flags, onVisibilityChangeListener); - } - - @Override - protected int createHideFlags() { - int flag = super.createHideFlags(); - - if (mLevel == SystemUiHelper.LEVEL_IMMERSIVE) { - // If the client requested immersive mode, and we're on Android 4.4 - // or later, add relevant flags. Applying HIDE_NAVIGATION without - // IMMERSIVE prevents the activity from accepting all touch events, - // so we only do this on Android 4.4 and later (where IMMERSIVE is - // present). - flag |= ((mFlags & SystemUiHelper.FLAG_IMMERSIVE_STICKY) != 0) - ? View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - : View.SYSTEM_UI_FLAG_IMMERSIVE; - } - - return flag; - } - -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.util.systemui; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.os.Build; +import android.view.View; + +@TargetApi(Build.VERSION_CODES.KITKAT) +class SystemUiHelperImplKK extends SystemUiHelperImplJB { + + SystemUiHelperImplKK(Activity activity, int level, int flags, + SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) { + super(activity, level, flags, onVisibilityChangeListener); + } + + @Override + protected int createHideFlags() { + int flag = super.createHideFlags(); + + if (mLevel == SystemUiHelper.LEVEL_IMMERSIVE) { + // If the client requested immersive mode, and we're on Android 4.4 + // or later, add relevant flags. Applying HIDE_NAVIGATION without + // IMMERSIVE prevents the activity from accepting all touch events, + // so we only do this on Android 4.4 and later (where IMMERSIVE is + // present). + flag |= ((mFlags & SystemUiHelper.FLAG_IMMERSIVE_STICKY) != 0) + ? View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + : View.SYSTEM_UI_FLAG_IMMERSIVE; + } + + return flag; + } + +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/CustomDrawerLayout.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/CustomDrawerLayout.java index 8308909..24ccc72 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/CustomDrawerLayout.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/CustomDrawerLayout.java @@ -1,49 +1,49 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.views; - -import android.content.Context; -import android.support.v4.widget.DrawerLayout; -import android.util.AttributeSet; -import android.view.KeyEvent; - -public class CustomDrawerLayout extends DrawerLayout{ - public CustomDrawerLayout(Context context) { - super(context); - } - - public CustomDrawerLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public CustomDrawerLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - return false; - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - return false; - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.views; + +import android.content.Context; +import android.support.v4.widget.DrawerLayout; +import android.util.AttributeSet; +import android.view.KeyEvent; + +public class CustomDrawerLayout extends DrawerLayout{ + public CustomDrawerLayout(Context context) { + super(context); + } + + public CustomDrawerLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CustomDrawerLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + return false; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + return false; + } +} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/GoodScrollView.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/GoodScrollView.java index a1d9942..7dad030 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/GoodScrollView.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/GoodScrollView.java @@ -1,84 +1,84 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -package sharedcode.turboeditor.views; - -import android.content.Context; -import android.os.Handler; -import android.util.AttributeSet; -import android.view.View; -import android.widget.ScrollView; - -public class GoodScrollView extends ScrollView { - - public ScrollInterface scrollInterface; - int lastY; - boolean listenerEnabled = true; - - public GoodScrollView(Context context) { - super(context); - } - - public GoodScrollView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public GoodScrollView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public void setScrollInterface(ScrollInterface scrollInterface) { - this.scrollInterface = scrollInterface; - } - - @Override - protected void onScrollChanged(int l, int t, int oldl, int oldt) { - super.onScrollChanged(l, t, oldl, oldt); - - if (scrollInterface == null || !listenerEnabled) return; - - if (Math.abs(lastY - t) > 100) { - lastY = t; - scrollInterface.onScrollChanged(l, t, oldl, oldt); - } - - } - - public boolean hasReachedBottom() { - View firstChild = getChildAt(getChildCount() - 1); - - int diff = (firstChild.getBottom() - (getHeight() + getScrollY() + firstChild.getTop()));// Calculate the scrolldiff - return diff <= 0; - } - - public void tempDisableListener(int mills) { - listenerEnabled = false; - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - listenerEnabled = true; - } - }, mills); - } - - - public interface ScrollInterface { - public void onScrollChanged(int l, int t, int oldl, int oldt); - } -} +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +package sharedcode.turboeditor.views; + +import android.content.Context; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ScrollView; + +public class GoodScrollView extends ScrollView { + + public ScrollInterface scrollInterface; + int lastY; + boolean listenerEnabled = true; + + public GoodScrollView(Context context) { + super(context); + } + + public GoodScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public GoodScrollView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void setScrollInterface(ScrollInterface scrollInterface) { + this.scrollInterface = scrollInterface; + } + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + + if (scrollInterface == null || !listenerEnabled) return; + + if (Math.abs(lastY - t) > 100) { + lastY = t; + scrollInterface.onScrollChanged(l, t, oldl, oldt); + } + + } + + public boolean hasReachedBottom() { + View firstChild = getChildAt(getChildCount() - 1); + + int diff = (firstChild.getBottom() - (getHeight() + getScrollY() + firstChild.getTop()));// Calculate the scrolldiff + return diff <= 0; + } + + public void tempDisableListener(int mills) { + listenerEnabled = false; + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + listenerEnabled = true; + } + }, mills); + } + + + public interface ScrollInterface { + public void onScrollChanged(int l, int t, int oldl, int oldt); + } +} diff --git a/libraries/sharedCode/src/main/res/layout/activity_home.xml b/libraries/sharedCode/src/main/res/layout/activity_home.xml index c18266f..1cb26e4 100644 --- a/libraries/sharedCode/src/main/res/layout/activity_home.xml +++ b/libraries/sharedCode/src/main/res/layout/activity_home.xml @@ -1,353 +1,353 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/activity_licenses.xml b/libraries/sharedCode/src/main/res/layout/activity_licenses.xml index 0086dde..86b6d10 100644 --- a/libraries/sharedCode/src/main/res/layout/activity_licenses.xml +++ b/libraries/sharedCode/src/main/res/layout/activity_licenses.xml @@ -1,31 +1,31 @@ - - - - + + + + diff --git a/libraries/sharedCode/src/main/res/layout/activity_select_file.xml b/libraries/sharedCode/src/main/res/layout/activity_select_file.xml index 284894d..9afcd02 100644 --- a/libraries/sharedCode/src/main/res/layout/activity_select_file.xml +++ b/libraries/sharedCode/src/main/res/layout/activity_select_file.xml @@ -1,60 +1,60 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/demo_changelog_fragment_dialogstandard.xml b/libraries/sharedCode/src/main/res/layout/demo_changelog_fragment_dialogstandard.xml index 489bf3e..e8eb328 100644 --- a/libraries/sharedCode/src/main/res/layout/demo_changelog_fragment_dialogstandard.xml +++ b/libraries/sharedCode/src/main/res/layout/demo_changelog_fragment_dialogstandard.xml @@ -1,28 +1,28 @@ - - - - + + + \ No newline at end of file diff --git a/libraries/sharedCode/src/main/res/layout/dialog_encoding_list.xml b/libraries/sharedCode/src/main/res/layout/dialog_encoding_list.xml index bc6c6b6..860ac04 100644 --- a/libraries/sharedCode/src/main/res/layout/dialog_encoding_list.xml +++ b/libraries/sharedCode/src/main/res/layout/dialog_encoding_list.xml @@ -1,46 +1,46 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/dialog_fragment_edittext.xml b/libraries/sharedCode/src/main/res/layout/dialog_fragment_edittext.xml index c437740..745b6af 100644 --- a/libraries/sharedCode/src/main/res/layout/dialog_fragment_edittext.xml +++ b/libraries/sharedCode/src/main/res/layout/dialog_fragment_edittext.xml @@ -1,37 +1,37 @@ - - - - - - - + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/dialog_fragment_file_info.xml b/libraries/sharedCode/src/main/res/layout/dialog_fragment_file_info.xml index a65cfa9..cfe85d5 100644 --- a/libraries/sharedCode/src/main/res/layout/dialog_fragment_file_info.xml +++ b/libraries/sharedCode/src/main/res/layout/dialog_fragment_file_info.xml @@ -1,32 +1,32 @@ - - - - - - - - + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/dialog_fragment_find_text.xml b/libraries/sharedCode/src/main/res/layout/dialog_fragment_find_text.xml index 12d9b31..e30b2a6 100644 --- a/libraries/sharedCode/src/main/res/layout/dialog_fragment_find_text.xml +++ b/libraries/sharedCode/src/main/res/layout/dialog_fragment_find_text.xml @@ -1,77 +1,77 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/dialog_fragment_new_file_details.xml b/libraries/sharedCode/src/main/res/layout/dialog_fragment_new_file_details.xml index 3f42e91..1964a11 100644 --- a/libraries/sharedCode/src/main/res/layout/dialog_fragment_new_file_details.xml +++ b/libraries/sharedCode/src/main/res/layout/dialog_fragment_new_file_details.xml @@ -1,61 +1,61 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/dialog_fragment_seekbar.xml b/libraries/sharedCode/src/main/res/layout/dialog_fragment_seekbar.xml index c09787d..6d01323 100644 --- a/libraries/sharedCode/src/main/res/layout/dialog_fragment_seekbar.xml +++ b/libraries/sharedCode/src/main/res/layout/dialog_fragment_seekbar.xml @@ -1,33 +1,33 @@ - - - - - - - - + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/fragment_reader_listview.xml b/libraries/sharedCode/src/main/res/layout/fragment_reader_listview.xml index 484f398..72d3bbd 100644 --- a/libraries/sharedCode/src/main/res/layout/fragment_reader_listview.xml +++ b/libraries/sharedCode/src/main/res/layout/fragment_reader_listview.xml @@ -1,27 +1,27 @@ - - - - - + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/fragment_settings.xml b/libraries/sharedCode/src/main/res/layout/fragment_settings.xml index 6cfcffb..7e93fb1 100644 --- a/libraries/sharedCode/src/main/res/layout/fragment_settings.xml +++ b/libraries/sharedCode/src/main/res/layout/fragment_settings.xml @@ -1,267 +1,267 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/sharedCode/src/main/res/layout/item_drawer_list.xml b/libraries/sharedCode/src/main/res/layout/item_drawer_list.xml index 42695d0..6b62f92 100644 --- a/libraries/sharedCode/src/main/res/layout/item_drawer_list.xml +++ b/libraries/sharedCode/src/main/res/layout/item_drawer_list.xml @@ -1,49 +1,49 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/item_file_list.xml b/libraries/sharedCode/src/main/res/layout/item_file_list.xml index b9b4720..22e5740 100644 --- a/libraries/sharedCode/src/main/res/layout/item_file_list.xml +++ b/libraries/sharedCode/src/main/res/layout/item_file_list.xml @@ -1,61 +1,61 @@ - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/item_single_choice.xml b/libraries/sharedCode/src/main/res/layout/item_single_choice.xml index cb1e909..4ad4528 100644 --- a/libraries/sharedCode/src/main/res/layout/item_single_choice.xml +++ b/libraries/sharedCode/src/main/res/layout/item_single_choice.xml @@ -1,32 +1,32 @@ - - - - + + + + diff --git a/libraries/sharedCode/src/main/res/layout/item_two_lines.xml b/libraries/sharedCode/src/main/res/layout/item_two_lines.xml index ca36e4e..e47fcde 100644 --- a/libraries/sharedCode/src/main/res/layout/item_two_lines.xml +++ b/libraries/sharedCode/src/main/res/layout/item_two_lines.xml @@ -1,58 +1,58 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/layout/toolbar.xml b/libraries/sharedCode/src/main/res/layout/toolbar.xml index 07267f5..bf8a02d 100644 --- a/libraries/sharedCode/src/main/res/layout/toolbar.xml +++ b/libraries/sharedCode/src/main/res/layout/toolbar.xml @@ -1,31 +1,31 @@ - - - - - + + + + \ No newline at end of file diff --git a/libraries/sharedCode/src/main/res/menu/activity_select_file.xml b/libraries/sharedCode/src/main/res/menu/activity_select_file.xml index 5f947bd..e4e568c 100644 --- a/libraries/sharedCode/src/main/res/menu/activity_select_file.xml +++ b/libraries/sharedCode/src/main/res/menu/activity_select_file.xml @@ -1,47 +1,47 @@ - - - -

- - - - - - - - - + + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/menu/fragment_editor.xml b/libraries/sharedCode/src/main/res/menu/fragment_editor.xml index fad5a8a..84f0a39 100644 --- a/libraries/sharedCode/src/main/res/menu/fragment_editor.xml +++ b/libraries/sharedCode/src/main/res/menu/fragment_editor.xml @@ -1,71 +1,71 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/menu/fragment_editor_search.xml b/libraries/sharedCode/src/main/res/menu/fragment_editor_search.xml index 2d1059a..266aebd 100644 --- a/libraries/sharedCode/src/main/res/menu/fragment_editor_search.xml +++ b/libraries/sharedCode/src/main/res/menu/fragment_editor_search.xml @@ -1,58 +1,58 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/menu/popup_new_file.xml b/libraries/sharedCode/src/main/res/menu/popup_new_file.xml index 4a1f10b..555d1e6 100644 --- a/libraries/sharedCode/src/main/res/menu/popup_new_file.xml +++ b/libraries/sharedCode/src/main/res/menu/popup_new_file.xml @@ -1,33 +1,33 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/libraries/sharedCode/src/main/res/raw/changelog.xml b/libraries/sharedCode/src/main/res/raw/changelog.xml index 958bb37..4e5cc9a 100644 --- a/libraries/sharedCode/src/main/res/raw/changelog.xml +++ b/libraries/sharedCode/src/main/res/raw/changelog.xml @@ -1,168 +1,168 @@ - - - - - - - Manly bug fixes - - - - Turbo Editor is a free and open source app. Now you can show your appreciation and support development by donating :) - New visual changes to make the app more "Material" - New save dialog when you are about to close a file - Many enchantments and fixes - Have feedback? Please use xda or the email. Thanks! - - - - Many enchantments and fixes - - - - [b]New! [/b]Important improvements to the syntax highlight - [b]New! [/b]Donation option in the about screen. Help to make Turbo Editor a better software! :) - [b]New! [/b]Setting to disable the "page system" - [b]New! [/b]Setting to ignore the back button - Fixed an issue related to cut/copy/past buttons - Other enchantments and fixes - - - - [b]New! [/b]Go To Line feature - Now the syntax highlight updates when scrolling - Other enchantments and fixs - - - - [b]New! [/b]Create empty files with just one click - [b]New! [/b]Read only mode - [b]New! [/b]Autosave function, to save files when the app loses focus - [b]New! [/b]Share the text from other apps to Turbo Editor - [b]New! [/b]Style changes - Other enchantments and fixs - - - - [b]New! [/b]Now you can open Very Big Files - [b]New! [/b]Better support for python and lua - Other enchantments and fixs - - - - [b]New! [/b]Find and Replace function - [b]New! [/b]Find with Regular Expression - [b]New! [/b]Right to Left support - [b]New! [/b]About screen - If a file was modified the app now asks to save the changes - Fixed an issue with the undo function - New animations - Other enchantments - - - - [b]New! [/b]Floating action button in the "Open a file" screen - [b]New! [/b]Set as working folder action in the "Open a file" screen - In the info/about screen added a link to the XDA thread - New menu icon for overflow - Updated the translations - Other enchantments - - - - [b]New! [/b]Added root features! - [b]New! [/b]Open hidden files - [b]New! [/b]GB2312 encoding - Other enchantments - - - - [b]New [/b] encoding dialog. There you can also enable/disable the auto encoding. - Added support to SQL and MATLAB - The font size dialog now shows the current font size - The background of the screens changes in relation to the selected theme - [b]Info[/b] The internet permission is used to show an Interstitial. The ad will be shown [b]at max once per day[/b]. - - - - [b]New![/b] Now you can search text inside the app! - - - - Now you can share the file! - Fixed many issues related to the keyboards - Added an option to activate suggestions and swipe functionality - - - - Fixed a Runtime Error, sorry :) - - - - Save, Undo and Redo actions are visible only when needed - [b]new![/b] Save with CTRL + S - More left space on the line numbers and changed their color - PHP variables now are highlight correctly - JS syntax highlight fixes - Fixed a bug with numbers inserted by certain keyboards - Updated translations - - - - [b]NOTE[/b] Syntax highlighting is updated when the cursor position changes - [b]SPECIAL NOTE[/b] If you like the app please rate it, but if you have some issue please tell me about them on the Google Plus Community, on the XDA thread or on Github :) - Now you can choose between light and dark theme - Fixed some issues with hard keyboards - Changed the size of line numbers to make them more readable - Increased file size limit - Optimized syntax color algorithm - Now you can create a new file without having to save it first - Bug fixes - - - - Now you can both wrap the text and view the line numbers - Optimized the line numbers algorithm - Clicking the X in the navigation drawer also closes the file - Menu titles corrected - Now list updates if a new folder is added - Resized the navigation drawer so it's not fullscreen on smaller devices - Now you can open files up to 50 kb. Be careful, you may experience crashes if you open files that are too big. - Minor fixes - - - - New Icons optimized for all the devices - Updated translations - Bug fixes - - - - Bug fixes - - - - Bug fixes - - - - First Version - - + + + + + + + Manly bug fixes + + + + Turbo Editor is a free and open source app. Now you can show your appreciation and support development by donating :) + New visual changes to make the app more "Material" + New save dialog when you are about to close a file + Many enchantments and fixes + Have feedback? Please use xda or the email. Thanks! + + + + Many enchantments and fixes + + + + [b]New! [/b]Important improvements to the syntax highlight + [b]New! [/b]Donation option in the about screen. Help to make Turbo Editor a better software! :) + [b]New! [/b]Setting to disable the "page system" + [b]New! [/b]Setting to ignore the back button + Fixed an issue related to cut/copy/past buttons + Other enchantments and fixes + + + + [b]New! [/b]Go To Line feature + Now the syntax highlight updates when scrolling + Other enchantments and fixs + + + + [b]New! [/b]Create empty files with just one click + [b]New! [/b]Read only mode + [b]New! [/b]Autosave function, to save files when the app loses focus + [b]New! [/b]Share the text from other apps to Turbo Editor + [b]New! [/b]Style changes + Other enchantments and fixs + + + + [b]New! [/b]Now you can open Very Big Files + [b]New! [/b]Better support for python and lua + Other enchantments and fixs + + + + [b]New! [/b]Find and Replace function + [b]New! [/b]Find with Regular Expression + [b]New! [/b]Right to Left support + [b]New! [/b]About screen + If a file was modified the app now asks to save the changes + Fixed an issue with the undo function + New animations + Other enchantments + + + + [b]New! [/b]Floating action button in the "Open a file" screen + [b]New! [/b]Set as working folder action in the "Open a file" screen + In the info/about screen added a link to the XDA thread + New menu icon for overflow + Updated the translations + Other enchantments + + + + [b]New! [/b]Added root features! + [b]New! [/b]Open hidden files + [b]New! [/b]GB2312 encoding + Other enchantments + + + + [b]New [/b] encoding dialog. There you can also enable/disable the auto encoding. + Added support to SQL and MATLAB + The font size dialog now shows the current font size + The background of the screens changes in relation to the selected theme + [b]Info[/b] The internet permission is used to show an Interstitial. The ad will be shown [b]at max once per day[/b]. + + + + [b]New![/b] Now you can search text inside the app! + + + + Now you can share the file! + Fixed many issues related to the keyboards + Added an option to activate suggestions and swipe functionality + + + + Fixed a Runtime Error, sorry :) + + + + Save, Undo and Redo actions are visible only when needed + [b]new![/b] Save with CTRL + S + More left space on the line numbers and changed their color + PHP variables now are highlight correctly + JS syntax highlight fixes + Fixed a bug with numbers inserted by certain keyboards + Updated translations + + + + [b]NOTE[/b] Syntax highlighting is updated when the cursor position changes + [b]SPECIAL NOTE[/b] If you like the app please rate it, but if you have some issue please tell me about them on the Google Plus Community, on the XDA thread or on Github :) + Now you can choose between light and dark theme + Fixed some issues with hard keyboards + Changed the size of line numbers to make them more readable + Increased file size limit + Optimized syntax color algorithm + Now you can create a new file without having to save it first + Bug fixes + + + + Now you can both wrap the text and view the line numbers + Optimized the line numbers algorithm + Clicking the X in the navigation drawer also closes the file + Menu titles corrected + Now list updates if a new folder is added + Resized the navigation drawer so it's not fullscreen on smaller devices + Now you can open files up to 50 kb. Be careful, you may experience crashes if you open files that are too big. + Minor fixes + + + + New Icons optimized for all the devices + Updated translations + Bug fixes + + + + Bug fixes + + + + Bug fixes + + + + First Version + + diff --git a/libraries/sharedCode/src/main/res/values-es-rMX/strings.xml b/libraries/sharedCode/src/main/res/values-es-rMX/strings.xml index d84567b..2e89f54 100644 --- a/libraries/sharedCode/src/main/res/values-es-rMX/strings.xml +++ b/libraries/sharedCode/src/main/res/values-es-rMX/strings.xml @@ -1,153 +1,153 @@ - - - - - - - Nueva cuenta - Activo - Borrar - Borrando archivos… - Subiendo… - Carpeta local actual - Llave privada - Claro - Codificación - Compartir - Nueva carpeta local - Nueva capeta remota - Nuevo archivo remoto - Nuevo archivo local - Desconectar - Carpeta local por defecto - Donde descargar? - Descargar - Descarga completa - Duplicar - Finalizado - Inicio - Servidor - Información - Local - Identificandote… - Editar - Mover - Oculto - Turbo Client - Turbo Editor - Nombre de usuario - Pasivo - Contraseña - Contraseña - Dejelo en blanco para rellenarlo en cada sesion - Puerto - Preferencias - Remoto - Para cambiar el tema, reinicie la aplicacion - Renombra - Carpeta remota predeterminada - Guardar - Oscuro - Seleccionar - Selecciona una cuenta - ¿Estás seguro? - Algo salio mal - No transferir el mismo archivo - Tema de la aplicación - Tipo de conexión - Tipo de protocolo - Otra carpeta - Usa una contraseña - Cargar - Subida finalizada - Que desea hacer? - Resalto de sintaxis - Deshacer - Rehacer - Sincronizar - Carpeta remota para sincronziar - Carpeta local para sincronizar - Vota - No se puede contactar con Google Play - Apoyar el desarrollo de otras características. - Actualizar a Premium - Actualizar a Premium y apoyar el desarrollo de Turbo Client! - Descargar version desbloqueada - ¿Que es Turbo Client? ¿Vale la pena? Fije su precio! - Actualice para desbloquear estas caracteristicas: - Poder para abrir y modificar cualquier tipo de archivo. - Servicio de copia de seguridad de copia de seguridad y restaurar sus datos de forma segura. - Desbloquear caracteristicas Premium - Le gusta esta aplicacion! - Me gusta esta aplicacion! - Copia de seguridad de las cuentas - Restaruar cuentas - Copia de seguridad y compartir las cuentas - Importortando cuentas… - Exportando las cuentas... - No se encontraron copias de seguridad - No se puede abrir el archivo - La carpeta temporal no existe - Se a producido un error - Interfaz de usuario - Remover - Fecha de modificacion - Nombre - Tamaño - Ordenar - Abrir - El archivo %1$s fue modificado, deseas subirlo? - El archivo %1$s se guardo correctamente! - Crear una cuenta nueva - Crear una nueva cuenta para comenzar. - Tipo - Enviar Comentarios - Copiar URL - Cortar - Pegar - Avanzado - Automatico - Bytes - Unidad de medida para el tamaño del archivo - Licencia de codigo abierto - Ver licencia de codigo abierto - Abrir un archivo - Abrir solo esta vez - Cambiar tipo de lista - Usar monoespacio - Archivos recientes - Tamaño de la fuente - Nombre de la conexion - Numero de linea - Wrap content - View it on the web - The file size is too big - Search - Add - File - Carpeta - Light Theme - Goto Line - Find - Find and Replace - Root Permission - Compartir - Text Suggestions - + + + + + + + Nueva cuenta + Activo + Borrar + Borrando archivos… + Subiendo… + Carpeta local actual + Llave privada + Claro + Codificación + Compartir + Nueva carpeta local + Nueva capeta remota + Nuevo archivo remoto + Nuevo archivo local + Desconectar + Carpeta local por defecto + Donde descargar? + Descargar + Descarga completa + Duplicar + Finalizado + Inicio + Servidor + Información + Local + Identificandote… + Editar + Mover + Oculto + Turbo Client + Turbo Editor + Nombre de usuario + Pasivo + Contraseña + Contraseña + Dejelo en blanco para rellenarlo en cada sesion + Puerto + Preferencias + Remoto + Para cambiar el tema, reinicie la aplicacion + Renombra + Carpeta remota predeterminada + Guardar + Oscuro + Seleccionar + Selecciona una cuenta + ¿Estás seguro? + Algo salio mal + No transferir el mismo archivo + Tema de la aplicación + Tipo de conexión + Tipo de protocolo + Otra carpeta + Usa una contraseña + Cargar + Subida finalizada + Que desea hacer? + Resalto de sintaxis + Deshacer + Rehacer + Sincronizar + Carpeta remota para sincronziar + Carpeta local para sincronizar + Vota + No se puede contactar con Google Play + Apoyar el desarrollo de otras características. + Actualizar a Premium + Actualizar a Premium y apoyar el desarrollo de Turbo Client! + Descargar version desbloqueada + ¿Que es Turbo Client? ¿Vale la pena? Fije su precio! + Actualice para desbloquear estas caracteristicas: + Poder para abrir y modificar cualquier tipo de archivo. + Servicio de copia de seguridad de copia de seguridad y restaurar sus datos de forma segura. + Desbloquear caracteristicas Premium + Le gusta esta aplicacion! + Me gusta esta aplicacion! + Copia de seguridad de las cuentas + Restaruar cuentas + Copia de seguridad y compartir las cuentas + Importortando cuentas… + Exportando las cuentas... + No se encontraron copias de seguridad + No se puede abrir el archivo + La carpeta temporal no existe + Se a producido un error + Interfaz de usuario + Remover + Fecha de modificacion + Nombre + Tamaño + Ordenar + Abrir + El archivo %1$s fue modificado, deseas subirlo? + El archivo %1$s se guardo correctamente! + Crear una cuenta nueva + Crear una nueva cuenta para comenzar. + Tipo + Enviar Comentarios + Copiar URL + Cortar + Pegar + Avanzado + Automatico + Bytes + Unidad de medida para el tamaño del archivo + Licencia de codigo abierto + Ver licencia de codigo abierto + Abrir un archivo + Abrir solo esta vez + Cambiar tipo de lista + Usar monoespacio + Archivos recientes + Tamaño de la fuente + Nombre de la conexion + Numero de linea + Wrap content + View it on the web + The file size is too big + Search + Add + File + Carpeta + Light Theme + Goto Line + Find + Find and Replace + Root Permission + Compartir + Text Suggestions + diff --git a/libraries/sharedCode/src/main/res/values-ms-rMY/strings.xml b/libraries/sharedCode/src/main/res/values-ms-rMY/strings.xml index a8cbb86..0972fb4 100644 --- a/libraries/sharedCode/src/main/res/values-ms-rMY/strings.xml +++ b/libraries/sharedCode/src/main/res/values-ms-rMY/strings.xml @@ -1,153 +1,153 @@ - - - - - - - Akaun Baru - Aktif - Buang - Menghapus fail... - Memproses... - Folder local sekarang - Kata kunci Private - Terang - Pengekodan - Kongsi - New local folder - New remote folder - New remote file - New local file - Putuskan sambungan - Folder local asal - Muat turun ke? - Muat turun - Muat turun selesai - Fail sudah wujud - Selesai - Home - Host - Maklumat - Local - Melog masuk... - Edit - Alih - Sembunyikan - Turbo Client - Turbo Editor - Kata Pengguna - Pasif - Kata Laluan - Kata Kunci - Biarkan kosong untuk ditanya setiap sesi - Port - Pilihan - Remote - Untuk mengubah tema, tutup dan buka semula aplikasi - Edit nama - root - Simpan - Gelap - Pilih - Pilih akaun - Anda pasti? - Something failed - Do not transfer same file - Tema aplikasi - Jenis sambungan - Jenis protokol - Folder lain - Guna kata laluan - Muat naik - Muat naik selesai - What do you want to do? - Syntax highlight - Batal edit - Buat semula edit - Sinkronisasi - Sinkronisasikan folder remote - Sinkronisasi folder local - Undi - Tidak dapat berhubung dengan Google Play - Sokong pembinaan ciri-ciri hebat yang lain. - Naik taraf kepada Premium - Menaiktaraf kepada Premium dan sokong perkembangan Turbo Client! - Download unlocked version - Apakah nilai Turbo Client pada anda? Berikan harga anda! - Naiktaraf untuk mendapat akses kepada ciri-ciri ini: - Membaca dan mengubahsuai apa-apa jenis fail. - Menyimpan dan mengambil semula data anda dengan selamat. - Akses ciri-ciri Premium - Saya sangat suka aplikasi ini! - Saya suka aplikasi ini! - Backup akaun - Kembalikan akaun - Backup dan kongsi akaun - Mengimport akaun… - Mengeksport akaun... - No backups found - Tidak dapat membuka fail - Temporary folder does not exist - An error occurred - antara muka pengguna - Hapus - Tarikh pengubahsuaian - Nama - Saiz - Susun - Buka - Fail %1$s telah berubah. Adakah anda mahu memuat naik? - The file %1$s was saved with success! - Cipta akaun baru - Create a new account to start. - Jenis - Send feedback - Copy URL - Cut - paste - Advanced - Auto - Bytes - Unit of measurement for file size - Open Source licenses - Show open source licenses - Open a file - Open this time only - Change the list type - Use monospace - Recent files - Font size - Connection Name - Line Numbers - Wrap content - View it on the web - The file size is too big - Search - Add - File - Folder - Light Theme - Goto Line - Find - Find and Replace - Root Permission - Kongsi - Text Suggestions - + + + + + + + Akaun Baru + Aktif + Buang + Menghapus fail... + Memproses... + Folder local sekarang + Kata kunci Private + Terang + Pengekodan + Kongsi + New local folder + New remote folder + New remote file + New local file + Putuskan sambungan + Folder local asal + Muat turun ke? + Muat turun + Muat turun selesai + Fail sudah wujud + Selesai + Home + Host + Maklumat + Local + Melog masuk... + Edit + Alih + Sembunyikan + Turbo Client + Turbo Editor + Kata Pengguna + Pasif + Kata Laluan + Kata Kunci + Biarkan kosong untuk ditanya setiap sesi + Port + Pilihan + Remote + Untuk mengubah tema, tutup dan buka semula aplikasi + Edit nama + root + Simpan + Gelap + Pilih + Pilih akaun + Anda pasti? + Something failed + Do not transfer same file + Tema aplikasi + Jenis sambungan + Jenis protokol + Folder lain + Guna kata laluan + Muat naik + Muat naik selesai + What do you want to do? + Syntax highlight + Batal edit + Buat semula edit + Sinkronisasi + Sinkronisasikan folder remote + Sinkronisasi folder local + Undi + Tidak dapat berhubung dengan Google Play + Sokong pembinaan ciri-ciri hebat yang lain. + Naik taraf kepada Premium + Menaiktaraf kepada Premium dan sokong perkembangan Turbo Client! + Download unlocked version + Apakah nilai Turbo Client pada anda? Berikan harga anda! + Naiktaraf untuk mendapat akses kepada ciri-ciri ini: + Membaca dan mengubahsuai apa-apa jenis fail. + Menyimpan dan mengambil semula data anda dengan selamat. + Akses ciri-ciri Premium + Saya sangat suka aplikasi ini! + Saya suka aplikasi ini! + Backup akaun + Kembalikan akaun + Backup dan kongsi akaun + Mengimport akaun… + Mengeksport akaun... + No backups found + Tidak dapat membuka fail + Temporary folder does not exist + An error occurred + antara muka pengguna + Hapus + Tarikh pengubahsuaian + Nama + Saiz + Susun + Buka + Fail %1$s telah berubah. Adakah anda mahu memuat naik? + The file %1$s was saved with success! + Cipta akaun baru + Create a new account to start. + Jenis + Send feedback + Copy URL + Cut + paste + Advanced + Auto + Bytes + Unit of measurement for file size + Open Source licenses + Show open source licenses + Open a file + Open this time only + Change the list type + Use monospace + Recent files + Font size + Connection Name + Line Numbers + Wrap content + View it on the web + The file size is too big + Search + Add + File + Folder + Light Theme + Goto Line + Find + Find and Replace + Root Permission + Kongsi + Text Suggestions + diff --git a/libraries/sharedCode/src/main/res/values-sk-rSK/strings.xml b/libraries/sharedCode/src/main/res/values-sk-rSK/strings.xml index 47542ec..7bb7364 100644 --- a/libraries/sharedCode/src/main/res/values-sk-rSK/strings.xml +++ b/libraries/sharedCode/src/main/res/values-sk-rSK/strings.xml @@ -1,153 +1,153 @@ - - - - - - - Nový účet - Aktívne - Vymazať - Mažem súbory… - Načítavanie… - Aktuálna miestna zložka - Súkromný kľúč - Svetlá - Kódovanie - Zdieľať - Nový lokálny súbor - Nový vzdialený priečinok - New remote file - New local file - Odpojiť sa - Predvol. miestna zložka - Kde oi chcete stiahnuť? - Stiahnuť - Sťahovanie dokončené - Duplikát - Hotovo - Domov - Hosť - Info - Lokálny - Prihlasujem sa… - Upraviť - Presunúť - Schovať - Turbo Klient - Turbo Editor - Užív. meno - Pasívny - Heslo - Heslo - Ponechajte prázdne, pre výzvu pri každej relácii - Port - Predvoľby - vzdialený - Pre zmenu témy, reštartujte aplikáciu - Premenovať - Root - Uložiť - Tmavá - Vybrať - Vyberte účet - Ste si istý? - Niečo zlyhalo - Nepresúvajte rovnaký súbor - Téma - Typ pripojenia - Typ protokolu - Ďalšia zložka - Napíš heslo - Nahrať - Nahrávanie dokončené - Čo chceš robiť? - Syntax highlight - Vrátiť späť - Prerobiť - Synchronizovať - Vzdial. zložka na synchronizáciu - Miestna zložka na synchronizáciu - Ohodnotiť - Nemožno kontaktovať Google Play - Podpor rozvoj ďalších skvelých funkcií. - Vylepšiť na Premium - Vylepši na Premium a podpor tým vývoj Turbo klienta! - Stiahnuť odomknutú verziu - Čo pre teba Turbo klient znamená? Stanov si vlastnú cenu! - Vylepši na Premium, pre odomknutie týchto funkcií: - Power to open and modify any type of file. - Backup service to backup and restore your data safely. - Unlock the Premium features - I really like this app! - I love this app! - Backup the accounts - Restore the accounts - Backup and share the accounts - Importing the accounts… - Exporting the accounts... - No backups found - Cannot open the file - Temporary folder does not exist - An error occurred - Ui - Remove - Modification date - Name - Size - Sort - Open - The file %1$s was modified, do you want to upload it? - The file %1$s was saved with success! - Create a new account - Create a new account to start. - Type - Send feedback - Copy URL - Cut - paste - Advanced - Auto - Bytes - Unit of measurement for file size - Open Source licenses - Show open source licenses - Open a file - Open this time only - Change the list type - Use monospace - Recent files - Font size - Connection Name - Line Numbers - Wrap content - View it on the web - The file size is too big - Search - Add - File - Folder - Light Theme - Goto Line - Find - Find and Replace - Root Permission - Zdieľať - Text Suggestions - + + + + + + + Nový účet + Aktívne + Vymazať + Mažem súbory… + Načítavanie… + Aktuálna miestna zložka + Súkromný kľúč + Svetlá + Kódovanie + Zdieľať + Nový lokálny súbor + Nový vzdialený priečinok + New remote file + New local file + Odpojiť sa + Predvol. miestna zložka + Kde oi chcete stiahnuť? + Stiahnuť + Sťahovanie dokončené + Duplikát + Hotovo + Domov + Hosť + Info + Lokálny + Prihlasujem sa… + Upraviť + Presunúť + Schovať + Turbo Klient + Turbo Editor + Užív. meno + Pasívny + Heslo + Heslo + Ponechajte prázdne, pre výzvu pri každej relácii + Port + Predvoľby + vzdialený + Pre zmenu témy, reštartujte aplikáciu + Premenovať + Root + Uložiť + Tmavá + Vybrať + Vyberte účet + Ste si istý? + Niečo zlyhalo + Nepresúvajte rovnaký súbor + Téma + Typ pripojenia + Typ protokolu + Ďalšia zložka + Napíš heslo + Nahrať + Nahrávanie dokončené + Čo chceš robiť? + Syntax highlight + Vrátiť späť + Prerobiť + Synchronizovať + Vzdial. zložka na synchronizáciu + Miestna zložka na synchronizáciu + Ohodnotiť + Nemožno kontaktovať Google Play + Podpor rozvoj ďalších skvelých funkcií. + Vylepšiť na Premium + Vylepši na Premium a podpor tým vývoj Turbo klienta! + Stiahnuť odomknutú verziu + Čo pre teba Turbo klient znamená? Stanov si vlastnú cenu! + Vylepši na Premium, pre odomknutie týchto funkcií: + Power to open and modify any type of file. + Backup service to backup and restore your data safely. + Unlock the Premium features + I really like this app! + I love this app! + Backup the accounts + Restore the accounts + Backup and share the accounts + Importing the accounts… + Exporting the accounts... + No backups found + Cannot open the file + Temporary folder does not exist + An error occurred + Ui + Remove + Modification date + Name + Size + Sort + Open + The file %1$s was modified, do you want to upload it? + The file %1$s was saved with success! + Create a new account + Create a new account to start. + Type + Send feedback + Copy URL + Cut + paste + Advanced + Auto + Bytes + Unit of measurement for file size + Open Source licenses + Show open source licenses + Open a file + Open this time only + Change the list type + Use monospace + Recent files + Font size + Connection Name + Line Numbers + Wrap content + View it on the web + The file size is too big + Search + Add + File + Folder + Light Theme + Goto Line + Find + Find and Replace + Root Permission + Zdieľať + Text Suggestions + diff --git a/libraries/sharedCode/src/main/res/values-w820dp/dimens.xml b/libraries/sharedCode/src/main/res/values-w820dp/dimens.xml index c91149f..74fcf1c 100644 --- a/libraries/sharedCode/src/main/res/values-w820dp/dimens.xml +++ b/libraries/sharedCode/src/main/res/values-w820dp/dimens.xml @@ -1,40 +1,40 @@ - - - - - 64dp - 64dp - - - 320dp - 10dp - 10dp - 1dp - 16dp - 72dp - 50dp - 10dp - 72dp - 2dp - 25sp - 16sp - 14sp - + + + + + 64dp + 64dp + + + 320dp + 10dp + 10dp + 1dp + 16dp + 72dp + 50dp + 10dp + 72dp + 2dp + 25sp + 16sp + 14sp + diff --git a/libraries/sharedCode/src/main/res/values-zh-rHK/strings.xml b/libraries/sharedCode/src/main/res/values-zh-rHK/strings.xml index 3ddcb8f..d52c4a2 100644 --- a/libraries/sharedCode/src/main/res/values-zh-rHK/strings.xml +++ b/libraries/sharedCode/src/main/res/values-zh-rHK/strings.xml @@ -1,153 +1,153 @@ - - - - - - - New account - 主動模式 - 刪除 - 刪除檔案中… - 載入中… - 本機資料夾 - 密鑰 - 明亮色系 - 編碼 - Share - New local folder - New remote folder - New remote file - New local file - 中斷連線 - 預設本機資料夾 - Where to download? - 下載 - Download completed - Duplicate - Done - Home - 主機 - 內容 - Local - 正在登入… - Edit - 移動 - Hide - Turbo Client - Turbo Editor - 帳戶 - 被動模式 - Passphrase - 密碼 - Leave it empty to prompt for it every session - 連接埠 - 選項 - Remote - To change the theme, restart the application - 重新命名 - 預設遠端資料夾 - 儲存 - 暗色系 - 選取 - 請選擇帳戶 - 確定繼續? - Something failed - Do not transfer same file - 佈景主題 - 連接類型 - 協定類型 - 另一個資料夾 - 使用 Passphrase - 上載 - Upload completed - What do you want to do? - Syntax highlight - 復原 - 重做 - 同步 - 同步的遠端資料夾 - 同步的本機資料夾 - 評分 - Cannot contact Google Play - Support the development of other great features. - Upgrade to Premium - Upgrade to Premium and support the development of Turbo Client! - Download unlocked version - What is Turbo Client worth to you? Set your price! - Upgrade to unlock this features: - Power to open and modify any type of file. - Backup service to backup and restore your data safely. - Unlock the Premium features - I really like this app! - I love this app! - Backup the accounts - Restore the accounts - Backup and share the accounts - Importing the accounts… - Exporting the accounts... - No backups found - Cannot open the file - Temporary folder does not exist - An error occurred - Ui - Remove - Modification date - Name - Size - Sort - Open - The file %1$s was modified, do you want to upload it? - The file %1$s was saved with success! - Create a new account - Create a new account to start. - Type - Send feedback - Copy URL - Cut - paste - Advanced - Auto - Bytes - Unit of measurement for file size - Open Source licenses - Show open source licenses - Open a file - Open this time only - Change the list type - Use monospace - Recent files - Font size - Connection Name - Line Numbers - Wrap content - View it on the web - The file size is too big - Search - Add - File - Folder - Light Theme - Goto Line - Find - Find and Replace - Root Permission - Share - Text Suggestions - + + + + + + + New account + 主動模式 + 刪除 + 刪除檔案中… + 載入中… + 本機資料夾 + 密鑰 + 明亮色系 + 編碼 + Share + New local folder + New remote folder + New remote file + New local file + 中斷連線 + 預設本機資料夾 + Where to download? + 下載 + Download completed + Duplicate + Done + Home + 主機 + 內容 + Local + 正在登入… + Edit + 移動 + Hide + Turbo Client + Turbo Editor + 帳戶 + 被動模式 + Passphrase + 密碼 + Leave it empty to prompt for it every session + 連接埠 + 選項 + Remote + To change the theme, restart the application + 重新命名 + 預設遠端資料夾 + 儲存 + 暗色系 + 選取 + 請選擇帳戶 + 確定繼續? + Something failed + Do not transfer same file + 佈景主題 + 連接類型 + 協定類型 + 另一個資料夾 + 使用 Passphrase + 上載 + Upload completed + What do you want to do? + Syntax highlight + 復原 + 重做 + 同步 + 同步的遠端資料夾 + 同步的本機資料夾 + 評分 + Cannot contact Google Play + Support the development of other great features. + Upgrade to Premium + Upgrade to Premium and support the development of Turbo Client! + Download unlocked version + What is Turbo Client worth to you? Set your price! + Upgrade to unlock this features: + Power to open and modify any type of file. + Backup service to backup and restore your data safely. + Unlock the Premium features + I really like this app! + I love this app! + Backup the accounts + Restore the accounts + Backup and share the accounts + Importing the accounts… + Exporting the accounts... + No backups found + Cannot open the file + Temporary folder does not exist + An error occurred + Ui + Remove + Modification date + Name + Size + Sort + Open + The file %1$s was modified, do you want to upload it? + The file %1$s was saved with success! + Create a new account + Create a new account to start. + Type + Send feedback + Copy URL + Cut + paste + Advanced + Auto + Bytes + Unit of measurement for file size + Open Source licenses + Show open source licenses + Open a file + Open this time only + Change the list type + Use monospace + Recent files + Font size + Connection Name + Line Numbers + Wrap content + View it on the web + The file size is too big + Search + Add + File + Folder + Light Theme + Goto Line + Find + Find and Replace + Root Permission + Share + Text Suggestions + diff --git a/libraries/sharedCode/src/main/res/values/arrays.xml b/libraries/sharedCode/src/main/res/values/arrays.xml index 0b71647..9de42dc 100644 --- a/libraries/sharedCode/src/main/res/values/arrays.xml +++ b/libraries/sharedCode/src/main/res/values/arrays.xml @@ -1,61 +1,61 @@ - - - - - - ChangeLog Library - EventBus - commons-io - RootCommands - Floating Action Button - - - - ISO-2022-JP - ISO-2022-CN - ISO-2022-KR - ISO-8859-5 - ISO-8859-7 - ISO-8859-8 - BIG5 - GB18030 - EUC-JP - EUC-KR - EUC-TW - SHIFT_JIS - IBM855 - IBM866 - KOI8-R - MACCYRILLIC - WINDOWS-1251 - WINDOWS-1252 - WINDOWS-1253 - WINDOWS-1255 - UTF-8 - UTF-16BE - UTF-16LE - UTF-32BE - UTF-32LE - GB2312 - HZ-GB-2312 - X-ISO-10646-UCS-4-3412 - X-ISO-10646-UCS-4-2143 - + + + + + + ChangeLog Library + EventBus + commons-io + RootCommands + Floating Action Button + + + + ISO-2022-JP + ISO-2022-CN + ISO-2022-KR + ISO-8859-5 + ISO-8859-7 + ISO-8859-8 + BIG5 + GB18030 + EUC-JP + EUC-KR + EUC-TW + SHIFT_JIS + IBM855 + IBM866 + KOI8-R + MACCYRILLIC + WINDOWS-1251 + WINDOWS-1252 + WINDOWS-1253 + WINDOWS-1255 + UTF-8 + UTF-16BE + UTF-16LE + UTF-32BE + UTF-32LE + GB2312 + HZ-GB-2312 + X-ISO-10646-UCS-4-3412 + X-ISO-10646-UCS-4-2143 + \ No newline at end of file diff --git a/libraries/sharedCode/src/main/res/values/attrs.xml b/libraries/sharedCode/src/main/res/values/attrs.xml index 573577d..75816f5 100644 --- a/libraries/sharedCode/src/main/res/values/attrs.xml +++ b/libraries/sharedCode/src/main/res/values/attrs.xml @@ -1,29 +1,29 @@ - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/sharedCode/src/main/res/values/colors.xml b/libraries/sharedCode/src/main/res/values/colors.xml index 49140d4..a19d67a 100644 --- a/libraries/sharedCode/src/main/res/values/colors.xml +++ b/libraries/sharedCode/src/main/res/values/colors.xml @@ -1,69 +1,69 @@ - - - - - - - - #212121 - #ffffff - #ffffffff - #ff212121 - #e5e5e5 - #ff2a2a2a - - #212121 - - #ffffff - #212121 - #f7f7f7 - #212121 - #666666 - #ffffffff - - #ffffff - #f7f7f7 - - #ffbb33 - #00a569 - #00a569 - #717171 - #aa66cc - #ff4444 - #33b5e5 - #ff00607d - - #ffff6600 - #ff2f6f9f - #ff4f9fcf - #ffd44950 - #ffd44950 - #ff009688 - #ff999999 - - #40969696 - #50000000 - #30000000 - - #b6cc45 - #DFED47 - - #607d8b + + + + + + + + #212121 + #ffffff + #ffffffff + #ff212121 + #e5e5e5 + #ff2a2a2a + + #212121 + + #ffffff + #212121 + #f7f7f7 + #212121 + #666666 + #ffffffff + + #ffffff + #f7f7f7 + + #ffbb33 + #00a569 + #00a569 + #717171 + #aa66cc + #ff4444 + #33b5e5 + #ff00607d + + #ffff6600 + #ff2f6f9f + #ff4f9fcf + #ffd44950 + #ffd44950 + #ff009688 + #ff999999 + + #40969696 + #50000000 + #30000000 + + #b6cc45 + #DFED47 + + #607d8b \ No newline at end of file diff --git a/libraries/sharedCode/src/main/res/values/dimens.xml b/libraries/sharedCode/src/main/res/values/dimens.xml index 2c2d8e9..62e9398 100644 --- a/libraries/sharedCode/src/main/res/values/dimens.xml +++ b/libraries/sharedCode/src/main/res/values/dimens.xml @@ -1,43 +1,43 @@ - - - - - 16dp - 16dp - 0dp - - - 300dp - 10dp - 10dp - 1dp - 16dp - 72dp - 50dp - 10dp - 72dp - 2dp - 25sp - 16sp - 14sp - - 56dp - + + + + + 16dp + 16dp + 0dp + + + 300dp + 10dp + 10dp + 1dp + 16dp + 72dp + 50dp + 10dp + 72dp + 2dp + 25sp + 16sp + 14sp + + 56dp + diff --git a/libraries/sharedCode/src/main/res/values/ids.xml b/libraries/sharedCode/src/main/res/values/ids.xml index 8f0858f..c549bfe 100644 --- a/libraries/sharedCode/src/main/res/values/ids.xml +++ b/libraries/sharedCode/src/main/res/values/ids.xml @@ -1,88 +1,88 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/values/integers.xml b/libraries/sharedCode/src/main/res/values/integers.xml index 2789c9a..5768659 100644 --- a/libraries/sharedCode/src/main/res/values/integers.xml +++ b/libraries/sharedCode/src/main/res/values/integers.xml @@ -1,23 +1,23 @@ - - - - - 4194304 - + + + + + 4194304 + diff --git a/libraries/sharedCode/src/main/res/values/strings.xml b/libraries/sharedCode/src/main/res/values/strings.xml index 00bc02a..72871dc 100644 --- a/libraries/sharedCode/src/main/res/values/strings.xml +++ b/libraries/sharedCode/src/main/res/values/strings.xml @@ -1,75 +1,75 @@ - - - - - - Use monospace - Recent files - Font size - Connection Name - Line Numbers - Wrap content - View it on the web - File - Folder - Light Theme - Go to Line… - Go to Page… - Find - Replace - Share - Keyboard suggestions and Swipe - Auto-Encoding - Set as the working folder - This is the working folder - Do you want to save the changes to the file %s? - Regular Expression - Text to find - Text to replace - Next - Previous - Please wait… - %s occurrences was found - v%s - Translate - Changelog - Match case - Long click for more options - Auto save - Read only - Send error reports - Extra options - Split the text if too long - Ignore back button - Encoding - Share - Info - Turbo Editor - Preferences - Save - Syntax highlight - Undo - Redo - Open - The file %1$s was saved with success! - Open a file - No - New file - + + + + + + Use monospace + Recent files + Font size + Connection Name + Line Numbers + Wrap content + View it on the web + File + Folder + Light Theme + Go to Line… + Go to Page… + Find + Replace + Share + Keyboard suggestions and Swipe + Auto-Encoding + Set as the working folder + This is the working folder + Do you want to save the changes to the file %s? + Regular Expression + Text to find + Text to replace + Next + Previous + Please wait… + %s occurrences was found + v%s + Translate + Changelog + Match case + Long click for more options + Auto save + Read only + Send error reports + Extra options + Split the text if too long + Ignore back button + Encoding + Share + Info + Turbo Editor + Preferences + Save + Syntax highlight + Undo + Redo + Open + The file %1$s was saved with success! + Open a file + No + New file + diff --git a/libraries/sharedCode/src/main/res/values/styles.xml b/libraries/sharedCode/src/main/res/values/styles.xml index 097f9f0..004ff14 100644 --- a/libraries/sharedCode/src/main/res/values/styles.xml +++ b/libraries/sharedCode/src/main/res/values/styles.xml @@ -1,87 +1,87 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/sharedCode/src/main/res/xml/extra_options.xml b/libraries/sharedCode/src/main/res/xml/extra_options.xml index 393e25f..4b0c733 100644 --- a/libraries/sharedCode/src/main/res/xml/extra_options.xml +++ b/libraries/sharedCode/src/main/res/xml/extra_options.xml @@ -1,69 +1,69 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/settings.gradle b/settings.gradle index 61c83c4..5537738 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,20 +1,20 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor 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. - * - * Turbo Editor 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 . - */ - -include ':app', ':libraries:RootCommands', ':libraries:FloatingActionButton', ':libraries:sharedCode', ':app-pro' +/* + * Copyright (C) 2014 Vlad Mihalachi + * + * This file is part of Turbo Editor. + * + * Turbo Editor 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. + * + * Turbo Editor 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 . + */ + +include ':app', ':libraries:RootCommands', ':libraries:FloatingActionButton', ':libraries:sharedCode', ':app-pro'